Beispiel #1
0
/**
 * Returns the default event loop object, this object is a global singleton
 * and it is not recommended to use it unless you require ChildEvent watchers
 * as they can only be attached to the default loop.
 * 
 * @return EventLoop
 */
PHP_METHOD(EventLoop, getDefaultLoop)
{
	/* Singleton */
	if( ! default_event_loop_object)
	{
		ALLOC_INIT_ZVAL(default_event_loop_object);
		
		/* Create object without calling constructor, we now have an EventLoop missing the ev_loop */
		if(object_init_ex(default_event_loop_object, event_loop_ce) != SUCCESS) {
			/* TODO: Error handling */
			RETURN_BOOL(0);
		
			return;
		}
		
		event_loop_object *obj = (event_loop_object *)zend_object_store_get_object(default_event_loop_object TSRMLS_CC);
		
		assert( ! obj->loop);
		
		/* TODO: allow other EVFLAGs */
		obj->loop = ev_default_loop(EVFLAG_AUTO);
		
		IF_DEBUG(ev_verify(obj->loop));
		IF_DEBUG(libev_printf("Created default_event_loop_object\n"));
	}
	
	/* Return copy, no destruct on our local zval */
	RETURN_ZVAL(default_event_loop_object, 1, 0);
}
Beispiel #2
0
PHP_METHOD(PeriodicEvent, again)
{
	/* TODO: Optional EventLoop parameter? */
	event_object *event_obj = (event_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
	
	if(event_has_loop(event_obj))
	{
		event_periodic_again(event_obj);
		
		if( ! event_is_active(event_obj) && ! event_is_pending(event_obj))
		{
			/* No longer referenced by libev, so remove GC protection */
			IF_DEBUG(libev_printf("ev_periodic_again() stopped non-repeating timer\n"));
			EVENT_LOOP_REF_DEL(event_obj);
		}
		
		RETURN_BOOL(1);
	}
	
	/* TODO: Throw exception */
	RETURN_BOOL(0);
}
Beispiel #3
0
/**
 * Feeds the given event set into the event loop, as if the specified event
 * had happened for the specified watcher.
 * 
 * The watcher will be GC protected until it has fired or clearPending is called
 * on it (unless you feed it again in the callback or add() it to an event loop
 * it won't accidentally be freed).
 * 
 * NOTE: As of libev 4.0.4; If you feed an event in the callback of a fed event,
 *       the newly fed event will be invoked before any other events (except other
 *       fed events). So do NOT create loops by re-feeding an event into the EventLoop
 *       as that loop will block just as much as a normal loop.
 * 
 * TODO: Add note about AsyncEvent when AsyncEvent is implemented
 * 
 * @param  Event
 * @return boolean  false if either the EventLoop or Event has not been initialized
 */
PHP_METHOD(EventLoop, feedEvent)
{
	int revents = 0;
	zval *event_obj;
	event_object *event;
	event_loop_object *loop_obj = (event_loop_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &event_obj, event_ce, &revents) != SUCCESS) {
		return;
	}
	
	event = (event_object *)zend_object_store_get_object(event_obj TSRMLS_CC);
	
	assert(loop_obj->loop);
	
	/* Only allow Events which are associated with this EventLoop
	   or those which are not associated with any EventLoop yet */
	if(loop_obj->loop &&
		( ! event_has_loop(event) || event_in_loop(loop_obj, event)))
	{
		IF_DEBUG(libev_printf("Feeding event with pending %d and active %d...",
			event_is_pending(event), event_is_active(event)));
		
		/* The event might already have a loop, no need to increase refcount */
		if( ! event_has_loop(event))
		{
			EVENT_LOOP_REF_ADD(event, loop_obj);
		}
		
		event_feed_event(loop_obj, event, revents);
		
		IF_DEBUG(php_printf(" done\n"));
		
		RETURN_BOOL(1);
	}
	
	RETURN_BOOL(0);
}
Beispiel #4
0
/**
 * Removes the event from the event loop, will skip all pending events on it too.
 * 
 * @param  Event
 * @return boolean  False if the Event is not associated with this EventLoop,
 *                  can also be false if there is an error
 */
PHP_METHOD(EventLoop, remove)
{
	zval *event_obj;
	event_object *event;
	event_loop_object *loop_obj = (event_loop_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &event_obj, event_ce) != SUCCESS) {
		return;
	}
	
	event = (event_object *)zend_object_store_get_object(event_obj TSRMLS_CC);
	
	assert(loop_obj->loop);
	
	if(loop_obj->loop && event_is_active(event))
	{
		assert(event->loop_obj);
		
		/* Check that the event is associated with us */
		if( ! event_in_loop(loop_obj, event))
		{
			IF_DEBUG(libev_printf("Event is not in this EventLoop\n"));
			
			RETURN_BOOL(0);
		}
		
		EVENT_STOP(event);
		
		/* Remove GC protection, no longer active or pending */
		EVENT_LOOP_REF_DEL(event);
		
		RETURN_BOOL(1);
	}
	
	RETURN_BOOL(0);
}
Beispiel #5
0
/**
 * Adds the event to the event loop.
 * 
 * This method will increase the refcount on the supplied Event, protecting it
 * from garbage collection. Refcount will be decreased on remove or if the
 * EventLoop object is GCd.
 * 
 * @param  Event
 * @return boolean
 */
PHP_METHOD(EventLoop, add)
{
	zval *zevent;
	event_object *event;
	event_loop_object *loop_obj = (event_loop_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
	
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zevent, event_ce) != SUCCESS) {
		return;
	}
	
	event = (event_object *)zend_object_store_get_object(zevent TSRMLS_CC);
	
	assert(loop_obj->loop);
	
	/* Check so the event is not associated with any EventLoop, also needs to check
	   for active, no need to perform logic if it already is started */
	if(loop_obj->loop && ! event_is_active(event))
	{
		if(event_has_loop(event))
		{
			if( ! event_in_loop(loop_obj, event))
			{
				/* Attempting to add a fed event to this EventLoop which
				   has been fed to another loop */
				IF_DEBUG(libev_printf("Attempting to add() an event already associated with another EventLoop\n"));
				RETURN_BOOL(0);
			}
		}
		
		EVENT_WATCHER_ACTION(event, loop_obj, start, io)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, timer)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, periodic)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, signal)
		else if(instance_of_class(event->std.ce, child_event_ce))
		{
			/* Special logic, ev_child can only be attached to the default loop */
			if( ! ev_is_default_loop(loop_obj->loop))
			{
				/* TODO: libev-specific exception class here */
				zend_throw_exception(NULL, "libev\\ChildEvent can only be added to the default event-loop", 1 TSRMLS_DC);
				
				return;
			}
			
			ev_child_start(loop_obj->loop, (ev_child *)event->watcher);
			IF_DEBUG(libev_printf("Calling ev_child_start\n"));
		}
		else EVENT_WATCHER_ACTION(event, loop_obj, start, stat)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, idle)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, async)
		else EVENT_WATCHER_ACTION(event, loop_obj, start, cleanup)
		
		if( ! event_has_loop(event))
		{
			/* GC protection */
			EVENT_LOOP_REF_ADD(event, loop_obj);
		}
		
		RETURN_BOOL(1);
	}
	
	RETURN_BOOL(0);
}