upnp/src/gena/gena_device.c
static void genaNotifyThread(
	/*! [in] notify thread structure containing all the headers and property set info. */
	void *input)
{
	subscription *sub;
	service_info *service;
	subscription sub_copy;
	notify_thread_struct *in = (notify_thread_struct *) input;
	int return_code;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	/* This should be a HandleLock and not a HandleReadLock otherwise if there
	 * is a lot of notifications, then multiple threads will acquire a read
	 * lock and the thread which sends the notification will be blocked forever
	 * on the HandleLock at the end of this function. */
	/*HandleReadLock(); */
	HandleLock();
	/* validate context */

	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}

	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service)) ||
	    copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
#ifdef UPNP_ENABLE_NOTIFICATION_REORDERING
	/*If the event is out of order push it back to the job queue */
	if (in->eventKey != sub->ToSendEventKey) {
		TPJobInit(&job, (start_routine) genaNotifyThread, input);
		TPJobSetFreeFunction(&job, (free_function) free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);
		/* Sleep a little before creating another thread otherwise if there is
		 * a lot of notifications to send, the device will take 100% of the CPU
		 * to create threads and push them back to the job queue. */
		imillisleep(1);
		ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		freeSubscription(&sub_copy);
		HandleUnlock();
		return;
	}
#endif

	HandleUnlock();

	/* send the notify */
	return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
	freeSubscription(&sub_copy);
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	/* validate context */
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service))) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	sub->ToSendEventKey++;
	if (sub->ToSendEventKey < 0)
		/* wrap to 1 for overflow */
		sub->ToSendEventKey = 1;
	if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
		RemoveSubscriptionSID(in->sid, service);
	free_notify_struct(in);

	HandleUnlock();
}
/*!
 * \brief Thread job to Notify a control point.
 *
 * It validates the subscription and copies the subscription. Also make sure
 * that events are sent in order.
 *
 * \note calls the genaNotify to do the actual work.
 */
\brief Thread job to Notify a control point.
It validates the subscription and copies the subscription. Also make sure
that events are sent in order.

\note calls the genaNotify to do the actual work.
\ brief Thread job to Notify a control point . It validates the subscription and copies the subscription . Also make sure that events are sent in order . \ note calls the genaNotify to do the actual work .
static void genaNotifyThread(
	void *input)
{
	subscription *sub;
	service_info *service;
	subscription sub_copy;
	notify_thread_struct *in = (notify_thread_struct *) input;
	int return_code;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;
	memset(&job, 0, sizeof(job));
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service)) ||
	    copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
#ifdef UPNP_ENABLE_NOTIFICATION_REORDERING
	if (in->eventKey != sub->ToSendEventKey) {
		TPJobInit(&job, (start_routine) genaNotifyThread, input);
		TPJobSetFreeFunction(&job, (free_function) free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);
		imillisleep(1);
		ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		freeSubscription(&sub_copy);
		HandleUnlock();
		return;
	}
#endif
	HandleUnlock();
	return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
	freeSubscription(&sub_copy);
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service))) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	sub->ToSendEventKey++;
	if (sub->ToSendEventKey < 0)
		sub->ToSendEventKey = 1;
	if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
		RemoveSubscriptionSID(in->sid, service);
	free_notify_struct(in);
	HandleUnlock();
}
static void genaNotifyThread ( void * input ) { subscription * sub ; service_info * service ; subscription sub_copy ; notify_thread_struct * in = ( notify_thread_struct * ) input ; int return_code ; struct Handle_Info * handle_info ; ThreadPoolJob job ; memset ( & job , 0 , sizeof ( job ) ) ; HandleLock ( ) ; if ( GetHandleInfo ( in -> device_handle , & handle_info ) != HND_DEVICE ) { free_notify_struct ( in ) ; HandleUnlock ( ) ; return ; } if ( ! ( service = FindServiceId ( & handle_info -> ServiceTable , in -> servId , in -> UDN ) ) || ! service -> active || ! ( sub = GetSubscriptionSID ( in -> sid , service ) ) || copy_subscription ( sub , & sub_copy ) != HTTP_SUCCESS ) { free_notify_struct ( in ) ; HandleUnlock ( ) ; return ; } #ifdef UPNP_ENABLE_NOTIFICATION_REORDERING if ( in -> eventKey != sub -> ToSendEventKey ) { TPJobInit ( & job , ( start_routine ) genaNotifyThread , input ) ; TPJobSetFreeFunction ( & job , ( free_function ) free_notify_struct ) ; TPJobSetPriority ( & job , MED_PRIORITY ) ; imillisleep ( 1 ) ; ThreadPoolAdd ( & gSendThreadPool , & job , NULL ) ; freeSubscription ( & sub_copy ) ; HandleUnlock ( ) ; return ; } #endif HandleUnlock ( ) ; return_code = genaNotify ( in -> headers , in -> propertySet , & sub_copy ) ; freeSubscription ( & sub_copy ) ; HandleLock ( ) ; if ( GetHandleInfo ( in -> device_handle , & handle_info ) != HND_DEVICE ) { free_notify_struct ( in ) ; HandleUnlock ( ) ; return ; } if ( ! ( service = FindServiceId ( & handle_info -> ServiceTable , in -> servId , in -> UDN ) ) || ! service -> active || ! ( sub = GetSubscriptionSID ( in -> sid , service ) ) ) { free_notify_struct ( in ) ; HandleUnlock ( ) ; return ; } sub -> ToSendEventKey ++ ; if ( sub -> ToSendEventKey < 0 ) sub -> ToSendEventKey = 1 ; if ( return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB ) RemoveSubscriptionSID ( in -> sid , service ) ; free_notify_struct ( in ) ; HandleUnlock ( ) ; }
\brief Thread job to Notify a control point.
\ brief Thread job to Notify a control point .
/*! [in] notify thread structure containing all the headers and property set info. */ /* This should be a HandleLock and not a HandleReadLock otherwise if there
	 * is a lot of notifications, then multiple threads will acquire a read
	 * lock and the thread which sends the notification will be blocked forever
	 * on the HandleLock at the end of this function. */ /*HandleReadLock(); */ /* validate context */ /*If the event is out of order push it back to the job queue */ /* Sleep a little before creating another thread otherwise if there is
		 * a lot of notifications to send, the device will take 100% of the CPU
		 * to create threads and push them back to the job queue. */ /* send the notify */ /* validate context */ /* wrap to 1 for overflow */