亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? io.c

?? 最新的libusb庫
?? C
?? 第 1 頁 / 共 5 頁
字號:
		poll(libusb file descriptors, 120*1000);		if (poll indicates activity)			libusb_handle_events_timeout(ctx, 0);	}	printf("completed!");	// other code here}\endcode * * Here we are <em>serializing</em> completion of an asynchronous event * against a condition - the condition being completion of a specific transfer. * The poll() loop has a long timeout to minimize CPU usage during situations * when nothing is happening (it could reasonably be unlimited). * * If this is the only thread that is polling libusb's file descriptors, there * is no problem: there is no danger that another thread will swallow up the * event that we are interested in. On the other hand, if there is another * thread polling the same descriptors, there is a chance that it will receive * the event that we were interested in. In this situation, <tt>myfunc()</tt> * will only realise that the transfer has completed on the next iteration of * the loop, <em>up to 120 seconds later.</em> Clearly a two-minute delay is * undesirable, and don't even think about using short timeouts to circumvent * this issue! *  * The solution here is to ensure that no two threads are ever polling the * file descriptors at the same time. A naive implementation of this would * impact the capabilities of the library, so libusb offers the scheme * documented below to ensure no loss of functionality. * * Before we go any further, it is worth mentioning that all libusb-wrapped * event handling procedures fully adhere to the scheme documented below. * This includes libusb_handle_events() and all the synchronous I/O functions -  * libusb hides this headache from you. You do not need to worry about any * of these issues if you stick to that level. * * The problem is when we consider the fact that libusb exposes file * descriptors to allow for you to integrate asynchronous USB I/O into * existing main loops, effectively allowing you to do some work behind * libusb's back. If you do take libusb's file descriptors and pass them to * poll()/select() yourself, you need to be aware of the associated issues. * * \section eventlock The events lock * * The first concept to be introduced is the events lock. The events lock * is used to serialize threads that want to handle events, such that only * one thread is handling events at any one time. * * You must take the events lock before polling libusb file descriptors, * using libusb_lock_events(). You must release the lock as soon as you have * aborted your poll()/select() loop, using libusb_unlock_events(). * * \section threadwait Letting other threads do the work for you * * Although the events lock is a critical part of the solution, it is not * enough on it's own. You might wonder if the following is sufficient...\code	libusb_lock_events(ctx);	while (!completed) {		poll(libusb file descriptors, 120*1000);		if (poll indicates activity)			libusb_handle_events_timeout(ctx, 0);	}	libusb_lock_events(ctx);\endcode * ...and the answer is that it is not. This is because the transfer in the * code shown above may take a long time (say 30 seconds) to complete, and * the lock is not released until the transfer is completed. * * Another thread with similar code that wants to do event handling may be * working with a transfer that completes after a few milliseconds. Despite * having such a quick completion time, the other thread cannot check that * status of its transfer until the code above has finished (30 seconds later) * due to contention on the lock. * * To solve this, libusb offers you a mechanism to determine when another * thread is handling events. It also offers a mechanism to block your thread * until the event handling thread has completed an event (and this mechanism * does not involve polling of file descriptors). * * After determining that another thread is currently handling events, you * obtain the <em>event waiters</em> lock using libusb_lock_event_waiters(). * You then re-check that some other thread is still handling events, and if * so, you call libusb_wait_for_event(). * * libusb_wait_for_event() puts your application to sleep until an event * occurs, or until a thread releases the events lock. When either of these * things happen, your thread is woken up, and should re-check the condition * it was waiting on. It should also re-check that another thread is handling * events, and if not, it should start handling events itself. * * This looks like the following, as pseudo-code:\coderetry:if (libusb_try_lock_events(ctx) == 0) {	// we obtained the event lock: do our own event handling	libusb_lock_events(ctx);	while (!completed) {		poll(libusb file descriptors, 120*1000);		if (poll indicates activity)			libusb_handle_events_locked(ctx, 0);	}	libusb_unlock_events(ctx);} else {	// another thread is doing event handling. wait for it to signal us that	// an event has completed	libusb_lock_event_waiters(ctx);	while (!completed) {		// now that we have the event waiters lock, double check that another		// thread is still handling events for us. (it may have ceased handling		// events in the time it took us to reach this point)		if (!libusb_event_handler_active(ctx)) {			// whoever was handling events is no longer doing so, try again			libusb_unlock_event_waiters(ctx);			goto retry;		}			libusb_wait_for_event(ctx);	}	libusb_unlock_event_waiters(ctx);}printf("completed!\n");\endcode * * We have now implemented code which can dynamically handle situations where * nobody is handling events (so we should do it ourselves), and it can also * handle situations where another thread is doing event handling (so we can * piggyback onto them). It is also equipped to handle a combination of * the two, for example, another thread is doing event handling, but for * whatever reason it stops doing so before our condition is met, so we take * over the event handling. * * Three functions were introduced in the above pseudo-code. Their importance * should be apparent from the code shown above. * -# libusb_try_lock_events() is a non-blocking function which attempts *    to acquire the events lock but returns a failure code if it is contended. * -# libusb_handle_events_locked() is a variant of *    libusb_handle_events_timeout() that you can call while holding the *    events lock. libusb_handle_events_timeout() itself implements similar *    logic to the above, so be sure not to call it when you are *    "working behind libusb's back", as is the case here. * -# libusb_event_handler_active() determines if someone is currently *    holding the events lock * * You might be wondering why there is no function to wake up all threads * blocked on libusb_wait_for_event(). This is because libusb can do this * internally: it will wake up all such threads when someone calls * libusb_unlock_events() or when a transfer completes (at the point after its * callback has returned). * * \subsection concl Closing remarks * * The above may seem a little complicated, but hopefully I have made it clear * why such complications are necessary. Also, do not forget that this only * applies to applications that take libusb's file descriptors and integrate * them into their own polling loops. * * You may decide that it is OK for your multi-threaded application to ignore * some of the rules and locks detailed above, because you don't think that * two threads can ever be polling the descriptors at the same time. If that * is the case, then that's good news for you because you don't have to worry. * But be careful here; remember that the synchronous I/O functions do event * handling internally. If you have one thread doing event handling in a loop * (without implementing the rules and locking semantics documented above) * and another trying to send a synchronous USB transfer, you will end up with * two threads monitoring the same descriptors, and the above-described * undesirable behaviour occuring. The solution is for your polling thread to * play by the rules; the synchronous I/O functions do so, and this will result * in them getting along in perfect harmony. * * If you do have a dedicated thread doing event handling, it is perfectly * legal for it to take the event handling lock and never release it. Any * synchronous I/O functions you call from other threads will transparently * fall back to the "event waiters" mechanism detailed above. */void usbi_io_init(struct libusb_context *ctx){	pthread_mutex_init(&ctx->flying_transfers_lock, NULL);	pthread_mutex_init(&ctx->pollfds_lock, NULL);	pthread_mutex_init(&ctx->events_lock, NULL);	pthread_mutex_init(&ctx->event_waiters_lock, NULL);	pthread_cond_init(&ctx->event_waiters_cond, NULL);	list_init(&ctx->flying_transfers);	list_init(&ctx->pollfds);}static int calculate_timeout(struct usbi_transfer *transfer){	int r;	struct timespec current_time;	unsigned int timeout =		__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;	if (!timeout)		return 0;	r = clock_gettime(CLOCK_MONOTONIC, &current_time);	if (r < 0) {		usbi_err(ITRANSFER_CTX(transfer),			"failed to read monotonic clock, errno=%d", errno);		return r;	}	current_time.tv_sec += timeout / 1000;	current_time.tv_nsec += (timeout % 1000) * 1000000;	if (current_time.tv_nsec > 1000000000) {		current_time.tv_nsec -= 1000000000;		current_time.tv_sec++;	}	TIMESPEC_TO_TIMEVAL(&transfer->timeout, &current_time);	return 0;}static void add_to_flying_list(struct usbi_transfer *transfer){	struct usbi_transfer *cur;	struct timeval *timeout = &transfer->timeout;	struct libusb_context *ctx = ITRANSFER_CTX(transfer);		pthread_mutex_lock(&ctx->flying_transfers_lock);	/* if we have no other flying transfers, start the list with this one */	if (list_empty(&ctx->flying_transfers)) {		list_add(&transfer->list, &ctx->flying_transfers);		goto out;	}	/* if we have infinite timeout, append to end of list */	if (!timerisset(timeout)) {		list_add_tail(&transfer->list, &ctx->flying_transfers);		goto out;	}	/* otherwise, find appropriate place in list */	list_for_each_entry(cur, &ctx->flying_transfers, list) {		/* find first timeout that occurs after the transfer in question */		struct timeval *cur_tv = &cur->timeout;		if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||				(cur_tv->tv_sec == timeout->tv_sec &&					cur_tv->tv_usec > timeout->tv_usec)) {			list_add_tail(&transfer->list, &cur->list);			goto out;		}	}	/* otherwise we need to be inserted at the end */	list_add_tail(&transfer->list, &ctx->flying_transfers);out:	pthread_mutex_unlock(&ctx->flying_transfers_lock);}/** \ingroup asyncio * Allocate a libusb transfer with a specified number of isochronous packet * descriptors. The returned transfer is pre-initialized for you. When the new * transfer is no longer needed, it should be freed with * libusb_free_transfer(). * * Transfers intended for non-isochronous endpoints (e.g. control, bulk, * interrupt) should specify an iso_packets count of zero. * * For transfers intended for isochronous endpoints, specify an appropriate * number of packet descriptors to be allocated as part of the transfer. * The returned transfer is not specially initialized for isochronous I/O; * you are still required to set the * \ref libusb_transfer::num_iso_packets "num_iso_packets" and * \ref libusb_transfer::type "type" fields accordingly. * * It is safe to allocate a transfer with some isochronous packets and then * use it on a non-isochronous endpoint. If you do this, ensure that at time * of submission, num_iso_packets is 0 and that type is set appropriately. * * \param iso_packets number of isochronous packet descriptors to allocate * \returns a newly allocated transfer, or NULL on error */API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(int iso_packets){	size_t os_alloc_size = usbi_backend->transfer_priv_size		+ (usbi_backend->add_iso_packet_size * iso_packets);	int alloc_size = sizeof(struct usbi_transfer)		+ sizeof(struct libusb_transfer)		+ (sizeof(struct libusb_iso_packet_descriptor) * iso_packets)		+ os_alloc_size;	struct usbi_transfer *itransfer = malloc(alloc_size);	if (!itransfer)		return NULL;	memset(itransfer, 0, alloc_size);	itransfer->num_iso_packets = iso_packets;	return __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);}/** \ingroup asyncio * Free a transfer structure. This should be called for all transfers * allocated with libusb_alloc_transfer(). * * If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER * "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is * non-NULL, this function will also free the transfer buffer using the * standard system memory allocator (e.g. free()). * * It is legal to call this function with a NULL transfer. In this case, * the function will simply return safely. * * \param transfer the transfer to free */API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer){	struct usbi_transfer *itransfer;	if (!transfer)		return;	if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer)		free(transfer->buffer);	itransfer = __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);	free(itransfer);}/** \ingroup asyncio * Submit a transfer. This function will fire off the USB transfer and then * return immediately. * * It is undefined behaviour to submit a transfer that has already been * submitted but has not yet completed. *

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
五月天一区二区| 亚洲免费成人av| 国产精品乱码久久久久久| 亚洲高清在线精品| 久久99国产精品久久99果冻传媒| 成人午夜在线免费| 日韩欧美色电影| 亚洲高清免费在线| 国产成人免费在线视频| 欧美一区午夜精品| 亚洲精品国产一区二区三区四区在线| 蜜乳av一区二区三区| 欧美日韩国产精选| 亚洲视频中文字幕| 国产99久久久国产精品潘金| 91精品欧美久久久久久动漫 | 成人免费高清在线| 日韩精品在线一区| 日本在线不卡视频一二三区| 一本久久精品一区二区| 国产精品久久久久久久久免费相片 | 亚洲精品国产品国语在线app| 精品一区二区三区不卡| 欧美一区二区性放荡片| 亚洲成av人片在线| 欧美丝袜第三区| 亚洲综合在线观看视频| 成人av免费在线| 国产精品国产三级国产有无不卡| 国产精品亚洲第一区在线暖暖韩国 | 精品影视av免费| 日韩一区二区在线观看| 亚洲在线视频免费观看| 欧美三级日韩三级国产三级| 亚洲主播在线播放| 欧美性xxxxx极品少妇| 一区二区三区免费在线观看| 日本韩国一区二区三区视频| 一区二区三区视频在线看| 91免费观看在线| 亚洲一本大道在线| 欧美一区二区三区免费视频 | 国产美女在线观看一区| 久久久青草青青国产亚洲免观| 激情文学综合丁香| 久久久久亚洲蜜桃| a亚洲天堂av| 亚洲精品videosex极品| 91黄视频在线观看| 爽爽淫人综合网网站| 精品欧美乱码久久久久久1区2区| 国产一区在线不卡| 最新国产成人在线观看| 欧美体内she精高潮| 青青国产91久久久久久| 久久精品夜色噜噜亚洲a∨| zzijzzij亚洲日本少妇熟睡| 亚洲永久精品国产| 日韩视频免费观看高清完整版在线观看 | 婷婷六月综合网| 日韩美女一区二区三区四区| 国产在线精品一区二区三区不卡 | 五月天国产精品| 精品噜噜噜噜久久久久久久久试看 | 蜜臀久久99精品久久久久久9| 精品久久国产老人久久综合| 懂色av一区二区三区免费观看 | 精品视频1区2区3区| 麻豆精品一区二区av白丝在线| 久久久不卡影院| 色综合天天狠狠| 麻豆91免费观看| 国产精品天天看| 777xxx欧美| 成人18视频日本| 美女mm1313爽爽久久久蜜臀| 亚洲欧洲韩国日本视频| 日韩欧美第一区| 91成人网在线| 国产精品乡下勾搭老头1| 亚洲国产另类av| 国产精品情趣视频| 日韩亚洲欧美在线| 91视频你懂的| 国产在线国偷精品免费看| 亚洲一区视频在线| 中文字幕精品三区| 91精品福利在线一区二区三区 | jlzzjlzz国产精品久久| 久久99精品网久久| 亚洲国产裸拍裸体视频在线观看乱了| 久久久国际精品| 欧美一二三四区在线| 欧美日韩在线不卡| 色老汉一区二区三区| 丰满少妇在线播放bd日韩电影| 免费美女久久99| 五月天国产精品| 亚洲国产日韩一区二区| 亚洲欧美日韩一区二区| 中文字幕中文乱码欧美一区二区| 26uuu欧美日本| 日韩精品自拍偷拍| 这里只有精品视频在线观看| 色综合天天综合在线视频| 成人免费毛片a| 国产69精品一区二区亚洲孕妇| 热久久免费视频| 日本在线不卡视频一二三区| 丝袜亚洲另类欧美综合| 亚洲第一在线综合网站| 亚洲国产成人porn| 亚洲国产一区二区视频| 午夜欧美视频在线观看| 午夜欧美2019年伦理| 亚洲成人免费看| 日韩高清在线观看| 看片网站欧美日韩| 国产又粗又猛又爽又黄91精品| a美女胸又www黄视频久久| 丁香婷婷综合激情五月色| 国产精品一二三区| 懂色中文一区二区在线播放| 成人动漫一区二区在线| 91理论电影在线观看| 欧洲一区二区三区免费视频| 在线国产亚洲欧美| 欧美精品久久一区二区三区| 制服丝袜激情欧洲亚洲| 2023国产精品| 国产精品动漫网站| 日韩国产在线一| 国产麻豆精品theporn| 成人自拍视频在线观看| 色综合中文字幕国产| 91在线视频18| 欧美精品日日鲁夜夜添| 精品国产一二三区| 国产精品视频一二三区| 亚洲男帅同性gay1069| 五月天久久比比资源色| 国产精品羞羞答答xxdd| 日本高清不卡aⅴ免费网站| 欧美狂野另类xxxxoooo| 久久亚洲二区三区| 亚洲综合在线免费观看| 九色综合狠狠综合久久| 99免费精品视频| 欧美一级日韩一级| 亚洲国产精华液网站w| 亚洲一区二区三区四区在线观看 | 欧美成人一区二区三区片免费| 久久久噜噜噜久久人人看| 亚洲精品国产a| 韩国精品主播一区二区在线观看| 日本精品视频一区二区三区| 在线电影院国产精品| 中文幕一区二区三区久久蜜桃| 亚洲国产精品一区二区www | 欧美激情一区二区在线| 亚洲gay无套男同| 成人免费观看视频| 欧美一级艳片视频免费观看| 中文字幕一区二区三区四区| 日韩激情一区二区| 一道本成人在线| 国产女主播一区| 男人的天堂久久精品| 91黄色免费观看| 久久精品亚洲精品国产欧美kt∨ | 国产精品久久三| 美女视频网站黄色亚洲| 色激情天天射综合网| 中文字幕欧美三区| 精品一区二区三区在线观看国产| 日本韩国精品在线| 国产色爱av资源综合区| 麻豆久久久久久久| 91精品国产综合久久福利| 亚洲精品国产一区二区精华液| 国产成人在线色| 久久久精品一品道一区| 激情综合网天天干| 欧美tickling挠脚心丨vk| 日韩激情视频在线观看| 欧美日韩第一区日日骚| 亚洲综合精品自拍| 色综合色综合色综合色综合色综合 | 亚洲一区免费视频| 成人中文字幕电影| 久久久亚洲国产美女国产盗摄| 久久99久久99精品免视看婷婷| 91精品国模一区二区三区| 亚洲成人一区二区在线观看| 91久久精品网| 亚洲午夜国产一区99re久久| 91久久精品一区二区三区| 亚洲美女偷拍久久| 91成人免费电影| 亚洲国产精品欧美一二99|