/** * Returns the remaining time until a timer fires, relative to the event loop * time. * * @return double * @return false if the TimerEvent is not associated with any EventLoop */ PHP_METHOD(TimerEvent, getRemaining) { event_object *event_obj = (event_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if(event_has_loop(event_obj)) { RETURN_DOUBLE(event_timer_remaining(event_obj)); } RETURN_BOOL(0); }
/** * Sends an event to the AsyncEvent object which will trigger it in the event * loop. * * @return boolean false if the object is not attached to an event loop */ PHP_METHOD(AsyncEvent, send) { event_object *obj = (event_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if(event_has_loop(obj)) { ev_async_send(obj->loop_obj->loop, (ev_async*)obj->watcher); RETURN_BOOL(1); } RETURN_BOOL(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); }
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); }
/** * 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); }