Commits

Ruslan Osmanov  committed 4a67c01

Change: removed loop arg from all watcher ctors, use default loop there
Add: EvLoop methods for creating watchers based on the loop
Add: ev_run, ev_break and other global stuff for the default loop
Fix: some segfaults, typos, eol
Add: config.m4: NDEBUG for non-debug mode

  • Participants
  • Parent commits 5cd7496

Comments (0)

Files changed (28)

 Getting rid of need to call ::start() method we skip the function call overhead!.
 
 
-Remove $loop arg from watcher class constructors, assume the default loop used.
-===============================================================================
+Whether static class Ev, or \Ev namespace for functions/properties associated with
+default loop
+===================================================================================
 
 
 libevent buffer functionality?
 	zend_fcall_info_cache  fcc           = empty_fcall_info_cache;
 	long                   priority      = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
-					&fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
+				&fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_check_class_entry_ptr);
-
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|z!l",
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 /* }}} */
 
 
-/* {{{ proto EvCheck::__construct(EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvCheck::__construct(callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvCheck, __construct)
 {
 	php_ev_check_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 	zend_fcall_info_cache  fcc           = empty_fcall_info_cache;
 	long                   priority      = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lbf|z!l",
-					&pid, &trace, &fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lbf|z!l",
+				&pid, &trace, &fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_child_class_entry_ptr);
-
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lbOf|z!l",
-					&pid, &trace, &loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 }
 /* }}} */
 
-/* {{{ proto EvChild::__construct(int pid, bool trace, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvChild::__construct(int pid, bool trace, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvChild, __construct)
 {
 	php_ev_child_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
   if test "$PHP_EV_DEBUG" != "no"; then
     CFLAGS="$CFLAGS -Wall -g -ggdb -O0"
     AC_DEFINE(PHP_EV_DEBUG, 1, [Enable ev debug support])
+  else
+    AC_DEFINE(NDEBUG, 1, [With NDEBUG defined assert generates no code])
   fi
 
   if test "$PHP_EV_SOCKETS" != "no"; then
 	zend_fcall_info_cache  fcc            = empty_fcall_info_cache;
 	long                   priority       = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|fz!l",
-					&loop_other, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO|fz!l",
-					&loop_other, ev_loop_class_entry_ptr,
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
-		self = getThis();
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|fz!l",
+				&loop_other, ev_loop_class_entry_ptr, &fci, &fcc,
+				&data, &priority) == FAILURE) {
+		return;
 	}
 
 	o_loop_other   = (php_ev_object *) zend_object_store_get_object(loop_other TSRMLS_CC);
 
 	PHP_EV_ASSERT(loop_other_ptr);
 
-	if (!self) { /* Factory */
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_embed_class_entry_ptr);
+
+		PHP_EV_ASSERT((self == NULL));
 		self = return_value; 
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
+		self = getThis();
 	}
 
 	embed_ptr = (php_ev_embed *) emalloc(sizeof(php_ev_embed));
 /* }}} */
 
 
-/* {{{ proto EvEmbed::__construct(EvLoop other, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvEmbed::__construct(EvLoop other, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvEmbed, __construct)
 {
 	php_ev_embed_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 
 /* Override `data` member of the watcher structs.
  * See types.h and libev/ev.h */
-#define EV_COMMON                                                                    \
-    zval                        *self;      /* this struct */                        \
-    zval                        *data;      /* custom var attached by user */        \
-    php_ev_loop                 *loop;                                               \
-    zend_fcall_info             *fci;       /* fci &fcc serve $callback arg */       \
-    zend_fcall_info_cache       *fcc;                                                \
-    int                          type;      /* EV_ *constant from libev/ev.h */      \
-    int                          e_flags;                                            \
-    void                        *e_prev;    /* Linked list of ev_watcher pointers */ \
-    PHP_EV_COMMON_THREAD_CTX;                                                        \
+#define EV_COMMON                                                                             \
+    zval                  *self;      /* this struct */                                       \
+    zval                  *data;      /* custom var attached by user */                       \
+    php_ev_loop           *loop;                                                              \
+    zend_fcall_info       *fci;       /* fci &fcc serve $callback arg */                      \
+    zend_fcall_info_cache *fcc;                                                               \
+    int                    type;      /* EV_ *constant from libev/ev.h */                     \
+    int                    e_flags;   /* PHP_EV_WATCHER_FLAG_ **/                             \
+    void                  *e_next;    /* Next item of doubly linked list(ev_watcher *) */     \
+    void                  *e_prev;    /* Previous item of doubly linked list(ev_watcher *) */ \
+    PHP_EV_COMMON_THREAD_CTX;
 
 #include "libev/ev.h"
 
 }
 /* }}} */
 
+/* {{{ php_ev_default_loop */
+zval *php_ev_default_loop(TSRMLS_D)
+{
+	zval **default_loop_ptr_ptr = &MyG(default_loop);
+
+	if (*default_loop_ptr_ptr) {
+		return *default_loop_ptr_ptr;
+	}
+
+	php_ev_object  *ev_obj;
+	struct ev_loop *loop   = ev_default_loop(EVFLAG_AUTO);
+
+	if (!loop) {
+		php_error_docref(NULL TSRMLS_CC, E_ERROR,
+				"Failed to instanciate default loop, "
+				"bad $LIBEV_FLAGS in environment?");
+		return 0;
+	}
+
+	MAKE_STD_ZVAL(*default_loop_ptr_ptr);
+	PHP_EV_INIT_CLASS_OBJECT(*default_loop_ptr_ptr, ev_loop_class_entry_ptr);
+
+	ev_obj = (php_ev_object *) zend_object_store_get_object(*default_loop_ptr_ptr TSRMLS_CC);
+
+	php_ev_loop *ptr = (php_ev_loop *) emalloc(sizeof(php_ev_loop));
+	memset(ptr, 0, sizeof(php_ev_loop));
+	ptr->loop = loop;
+
+	ev_obj->ptr = (void *) ptr;
+
+	ev_set_userdata(loop, (void *) *default_loop_ptr_ptr);
+
+	return *default_loop_ptr_ptr;
+}
+/* }}} */
+
 /* {{{ php_ev_prop_read_default */
 static int php_ev_prop_read_default(php_ev_object *obj, zval **retval TSRMLS_DC)
 {
 	php_ev_loop *ptr = (php_ev_loop *) obj->ptr;
 
 	if (ptr->loop) {
-		/* Stop all watchers associated with this loop.  But don't free their memory. 
-		 * They have special automatically called handlers for this purpose */
+		/* Don't free memory of watchers here.
+		 * They have special GC handlers for this purpose */
 		ev_watcher *w = ptr->w;
 		while (w) {
-			php_ev_stop_watcher(w TSRMLS_CC);
-			w = php_ev_watcher_prev(w);
+			/* Watcher is stopped in it's cleanup handler
+			 * php_ev_stop_watcher(w TSRMLS_CC);*/
+			php_ev_watcher_loop(w) = NULL;
+			w = php_ev_watcher_next(w);
 		}
 
 		if (ev_is_default_loop(ptr->loop)) {
  * This is a helper for derived watcher class objects. */
 static void php_ev_watcher_free_storage(ev_watcher *ptr TSRMLS_DC)
 {
-	zval *data, *self;
+	zval       *data;
+	ev_watcher *w_next  , *w_prev;
 
-	/* This is done in php_ev_loop_free_storage()
+	/* What if we do it in php_ev_loop_free_storage()?*/
 	php_ev_stop_watcher(ptr TSRMLS_CC);
-	*/
+
+	/* Re-link the list of watchers */
+
+	w_next = php_ev_watcher_next(ptr);
+	w_prev = php_ev_watcher_prev(ptr);
+
+	if (w_prev) {
+		php_ev_watcher_next(w_prev) = w_next;
+	}
+
+	if (w_next) {
+		php_ev_watcher_prev(w_next) = w_prev;
+	}
+
+#if 0
+	php_ev_loop *o_loop = php_ev_watcher_loop(ptr);
+	if (o_loop) {
+		ev_watcher *pw = o_loop->w;
+
+		if (pw == ptr) { /* head of the list */
+			o_loop->w = w_next;
+		} else {
+			while (pw) {
+				if (php_ev_watcher_next(pw) == ptr) {
+					/* pw is the next watcher after ptr */
+					php_ev_watcher_next(pw) = w_next;
+					break;
+				}
+				pw = php_ev_watcher_next(pw);
+			}
+		}
+	}
+#endif
+
+	php_ev_watcher_next(ptr) = php_ev_watcher_prev(ptr) = NULL;
 
 	PHP_EV_FREE_FCALL_INFO(php_ev_watcher_fci(ptr), php_ev_watcher_fcc(ptr));
 	
 	data = php_ev_watcher_data(ptr);
-	self = php_ev_watcher_self(ptr);
-
 	if (data) {
 		zval_ptr_dtor(&data);
 	}
-	zval_ptr_dtor(&self);
+
+	zval_ptr_dtor(&php_ev_watcher_self(ptr));
 }
 /* }}} */
 
 	}
 
 	retval.handle = zend_objects_store_put(intern,
-			(zend_objects_store_dtor_t)zend_objects_destroy_object,
-			(zend_objects_free_object_storage_t)func_free_storage,
+			(zend_objects_store_dtor_t) zend_objects_destroy_object,
+			(zend_objects_free_object_storage_t) func_free_storage,
 			NULL TSRMLS_CC);
 	retval.handlers = &ev_object_handlers;
 
 }
 /* }}} */
 
+/* {{{ proto void ev_run([int flags = 0]) */
+PHP_FUNCTION(ev_run)
+{
+	long flags = 0;
+	zval *zloop;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
+		return;
+	}
+
+	zloop = php_ev_default_loop(TSRMLS_C);
+
+	php_ev_object *ev_obj = (php_ev_object *) zend_object_store_get_object(zloop TSRMLS_CC);
+	PHP_EV_CONSTRUCT_CHECK(ev_obj);
+
+	ev_run(PHP_EV_LOOP_FETCH_FROM_OBJECT(ev_obj), flags);
+}
+/* }}} */
+
+/* {{{ proto double ev_now(void) */
+PHP_FUNCTION(ev_now)
+{
+	zval           *zloop  = php_ev_default_loop(TSRMLS_C);
+	php_ev_object  *ev_obj;
+
+	if (zend_parse_parameters_none() == FAILURE) {
+		return;
+	}
+
+	ev_obj = (php_ev_object *) zend_object_store_get_object(zloop TSRMLS_CC);
+	PHP_EV_CONSTRUCT_CHECK(ev_obj);
+
+	RETURN_DOUBLE((double) ev_now(PHP_EV_LOOP_FETCH_FROM_OBJECT(ev_obj)));
+}
+/* }}} */
+
+/* {{{ proto void ev_break([int how = 0]) */
+PHP_FUNCTION(ev_break)
+{
+	long  how   = EVBREAK_ONE;
+	zval *zloop;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &how) == FAILURE) {
+		return;
+	}
+
+	zloop = php_ev_default_loop(TSRMLS_C);
+
+	php_ev_object *ev_obj = (php_ev_object *) zend_object_store_get_object(zloop TSRMLS_CC);
+	PHP_EV_CONSTRUCT_CHECK(ev_obj);
+
+	ev_break(PHP_EV_LOOP_FETCH_FROM_OBJECT(ev_obj), how);
+}
+/* }}} */
+
 /* }}} */
 
 #endif /* HAVE_EV */
 
 /* {{{ ARGINFO */
 
+/* TODO: Refactor: some arginfoes can be identical,
+ * e.g. EvLoop::io() and EvIo::__construct() */
+
 ZEND_BEGIN_ARG_INFO(arginfo_ev__void, 0)
 ZEND_END_ARG_INFO();
 
 /* EvWatcher }}} */
 
 /* {{{ EvIo */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_io, 0, 0, 4)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_io, 0, 0, 3)
 	ZEND_ARG_INFO(0, fd)
 	ZEND_ARG_INFO(0, events)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 /* EvIo }}} */
 
 /* {{{ EvTimer */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_timer, 0, 0, 4)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_timer, 0, 0, 3)
 	ZEND_ARG_INFO(0, after)
 	ZEND_ARG_INFO(0, repeat)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_PERIODIC_ENABLE
 /* {{{ EvPeriodic */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_periodic, 0, 0, 4)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_periodic, 0, 0, 3)
 	ZEND_ARG_INFO(0, offset)
 	ZEND_ARG_INFO(0, interval)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_SIGNAL_ENABLE
 /* {{{ EvSignal*/
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_signal, 0, 0, 3)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_signal, 0, 0, 2)
 	ZEND_ARG_INFO(0, signum)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_CHILD_ENABLE
 /* {{{ EvChild*/
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_child, 0, 0, 4)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_child, 0, 0, 3)
 	ZEND_ARG_INFO(0, pid)
 	ZEND_ARG_INFO(0, trace)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_STAT_ENABLE
 /* {{{ EvStat */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_stat, 0, 0, 4)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_stat, 0, 0, 3)
 	ZEND_ARG_INFO(0, path)
 	ZEND_ARG_INFO(0, interval)
-	ZEND_ARG_INFO(0, loop)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_IDLE_ENABLE
 /* {{{ EvIdle */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_idle, 0, 0, 2)
-	ZEND_ARG_INFO(0, loop)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_idle, 0, 0, 1)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_CHECK_ENABLE
 /* {{{ EvCheck */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_check, 0, 0, 2)
-	ZEND_ARG_INFO(0, loop)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_check, 0, 0, 1)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_PREPARE_ENABLE
 /* {{{ EvPrepare */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_prepare, 0, 0, 2)
-	ZEND_ARG_INFO(0, loop)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_prepare, 0, 0, 1)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 
 #if EV_EMBED_ENABLE
 /* {{{ EvEmbed */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_embed, 0, 0, 2)
-	ZEND_ARG_INFO(0, loop)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_embed, 0, 0, 1)
 	ZEND_ARG_INFO(0, other)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 ZEND_END_ARG_INFO();
+
 ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_embed_set, 0, 0, 1)
 	ZEND_ARG_INFO(0, other)
 ZEND_END_ARG_INFO();
 
 #if EV_FORK_ENABLE
 /* {{{ EvFork */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_fork, 0, 0, 2)
-	ZEND_ARG_INFO(0, loop)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_fork, 0, 0, 1)
 	ZEND_ARG_INFO(0, callback)
 	ZEND_ARG_INFO(0, data)
 	ZEND_ARG_INFO(0, priority)
 	PHP_FE(ev_sleep,                arginfo_ev_sleep)
 	PHP_FE(ev_time,                 arginfo_ev__void)
 	PHP_FE(ev_feed_signal,          arginfo_ev_feed_signal)
+	PHP_FE(ev_run,                  arginfo_ev_run)
+	PHP_FE(ev_now,                  arginfo_ev__void)
+	PHP_FE(ev_break,                arginfo_ev_break)
 
 	{NULL, NULL, NULL}
 };
 PHP_FUNCTION(ev_feed_signal);
 PHP_FUNCTION(ev_sleep);
 PHP_FUNCTION(ev_time);
+PHP_FUNCTION(ev_run);
+PHP_FUNCTION(ev_now);
+PHP_FUNCTION(ev_break);
 
 /* {{{ EvLoop */
 PHP_METHOD(EvLoop, __construct);
 	zend_fcall_info_cache  fcc          = empty_fcall_info_cache;
 	long                   priority     = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
-					&fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
+				&fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_fork_class_entry_ptr);
-
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|z!l",
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 	zend_fcall_info_cache  fcc          = empty_fcall_info_cache;
 	long                   priority     = 0;
 
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
+				&fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
-					&fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
-
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_idle_class_entry_ptr);
-
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|z!l",
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 }
 /* }}} */
 
-/* {{{ proto EvIdle::__construct(EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvIdle::__construct(callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvIdle, __construct)
 {
 	php_ev_idle_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 	long                   priority   = 0;
 	long                   events;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zlf|z!l",
-					&z_fd, &events, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zlOf|z!l",
-					&z_fd, &events, &loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
-		self = getThis();
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zlf|z!l",
+				&z_fd, &events, &fci, &fcc,
+				&data, &priority) == FAILURE) {
+		return;
 	}
 
 	if (events & ~(EV_READ | EV_WRITE)) {
 		return;
 	}
 
-	if (!self) { /* Factory */
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_io_class_entry_ptr);
+
+		PHP_EV_ASSERT((self == NULL));
 		self = return_value; 
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
+		self = getThis();
 	}
 
-	o_self  = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
-	o_loop  = (php_ev_object *) zend_object_store_get_object(loop TSRMLS_CC);
+	o_self     = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
+	o_loop     = (php_ev_object *) zend_object_store_get_object(loop TSRMLS_CC);
 	io_watcher = (ev_io *) php_ev_new_watcher(sizeof(ev_io), self,
 			PHP_EV_LOOP_OBJECT_FETCH_FROM_OBJECT(o_loop),
 			&fci, &fcc, data, priority TSRMLS_CC);
 /* }}} */
 
 
-/* {{{ proto EvIo::__construct(mixed fd, int events, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvIo::__construct(mixed fd, int events, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvIo, __construct)
 {
 	php_ev_io_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 	php_ev_object          *ev_obj;
 	ev_loop                *loop;
 	zval                  **default_loop_ptr_ptr     = NULL;
-	zval                   *self                     = getThis();
 
 	long                    flags                    = EVFLAG_AUTO;
 	double                  io_collect_interval      = 0.;
 	if (!in_ctor) {
 		/* Factory method mode */
 		if (is_default_loop) {
+
 			if (!*default_loop_ptr_ptr) {
 				loop = ev_default_loop(flags);
 			} else {
 				php_error_docref(NULL TSRMLS_CC, E_WARNING,
 						"Returning previously created default loop");
 				RETURN_ZVAL(*default_loop_ptr_ptr, /* copy */ 1, /* dtor*/ 0);
-				return;
 			}
 		} else {
 			loop = ev_loop_new(flags);
 			return;
 		}
 
-		/* Assign return value */
-		Z_TYPE_P(return_value) = IS_OBJECT;
-		object_init_ex(return_value, ev_loop_class_entry_ptr);
-		Z_SET_REFCOUNT_P(return_value, 1);
-		Z_UNSET_ISREF_P(return_value);
+		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_loop_class_entry_ptr);
 
 		ev_obj = (php_ev_object *) zend_object_store_get_object(return_value TSRMLS_CC);
 
 			return;
 		}
 
-		ev_obj = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
+		ev_obj = (php_ev_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
 	}
 
 	php_ev_loop *ptr = (php_ev_loop *) emalloc(sizeof(php_ev_loop));
         Z_TYPE_P(pz) = IS_OBJECT;         \
         object_init_ex(pz, pce);          \
         Z_SET_REFCOUNT_P(pz, 1);          \
-        Z_UNSET_ISREF_P(pz);
+        Z_SET_ISREF_P(pz)
 
 #define PHP_EV_ADD_CLASS_PROPERTIES(a, b)                                                      \
 {                                                                                              \
    +----------------------------------------------------------------------+
 */
 
+#if 0
 #include "embed.h"
 #include "priv.h"
+#endif
+#include "php_ev.h"
 #include "watcher.h"
 
+
 /* {{{ EvLoop property handlers */
 
 /* {{{ ev_loop_prop_data_read  */
 	zend_fcall_info_cache  fcc              = empty_fcall_info_cache;
 	long                   priority         = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddf!f|z!l",
-					&offset, &interval, &fci_reschedule, &fcc_reschedule,
-					&fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddf!Of|z!l",
-					&offset, &interval, &fci_reschedule, &fcc_reschedule,
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
-		self = getThis();
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddf!f|z!l",
+				&offset, &interval, &fci_reschedule, &fcc_reschedule,
+				&fci, &fcc, &data, &priority) == FAILURE) {
+		return;
 	}
 
 	PHP_EV_CHECK_REPEAT(interval);
 
-	if (!self) { /* Factory */
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_periodic_class_entry_ptr);
+
+		PHP_EV_ASSERT((self == NULL));
 		self = return_value; 
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
+		self = getThis();
 	}
 
 	periodic_ptr = (php_ev_periodic *) emalloc(sizeof(php_ev_periodic));
 
 	periodic_watcher = &periodic_ptr->periodic;
 
-	o_self           = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
-	o_loop           = (php_ev_object *) zend_object_store_get_object(loop TSRMLS_CC);
+	o_self = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
+	o_loop = (php_ev_object *) zend_object_store_get_object(loop TSRMLS_CC);
 
 	php_ev_set_watcher((ev_watcher *)periodic_watcher, sizeof(ev_periodic), self,
 			PHP_EV_LOOP_OBJECT_FETCH_FROM_OBJECT(o_loop),
 /* }}} */
 
 
-/* {{{ proto EvPeriodic::__construct(double offset, double interval, callable reschedule_cb, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) 
+/* {{{ proto EvPeriodic::__construct(double offset, double interval, callable reschedule_cb, callable callback[, mixed data = NULL[, int priority = 0]]) 
  * NOTE: reschedule_cb could be NULL */
 PHP_METHOD(EvPeriodic, __construct)
 {
 ZEND_BEGIN_MODULE_GLOBALS(ev)
 	zval *default_loop;
 ZEND_END_MODULE_GLOBALS(ev)
+ZEND_EXTERN_MODULE_GLOBALS(ev)
 
 extern zend_module_entry ev_module_entry;
 #define phpext_ev_ptr &ev_module_entry
 	zend_fcall_info_cache  fcc             = empty_fcall_info_cache;
 	long                   priority        = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
-					&fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f|z!l",
+				&fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_prepare_class_entry_ptr);
-
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of|z!l",
-					&loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 /* }}} */
 
 
-/* {{{ proto EvPrepare::__construct(EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvPrepare::__construct(callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvPrepare, __construct)
 {
 	php_ev_prepare_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 extern const zend_property_info ev_stat_property_entry_info[];
 extern const zend_property_info ev_embed_property_entry_info[];
 
+zval *php_ev_default_loop(TSRMLS_D);
+
 void php_ev_io_object_ctor(INTERNAL_FUNCTION_PARAMETERS, zval *loop);
 void php_ev_timer_object_ctor(INTERNAL_FUNCTION_PARAMETERS, zval *loop);
 void php_ev_periodic_object_ctor(INTERNAL_FUNCTION_PARAMETERS, zval *loop);
 	zend_fcall_info_cache  fcc        = empty_fcall_info_cache;
 	long                   priority   = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lf|z!l",
-					&signum, &fci, &fcc, &data, &priority) == FAILURE) {
-			return;
-		}
-
-		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_periodic_class_entry_ptr);
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lf|z!l",
+				&signum, &fci, &fcc, &data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
+		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_signal_class_entry_ptr);
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lOf|z!l",
-					&signum, &loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 }
 /* }}} */
 
-/* {{{ proto EvSignal::__construct(int signum, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvSignal::__construct(int signum, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvSignal, __construct)
 {
 	php_ev_signal_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 	long                   priority     = 0;
 
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pdf|z!l",
-					&path, &path_len, &interval, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pdf|z!l",
+				&path, &path_len, &interval, &fci, &fcc,
+				&data, &priority) == FAILURE) {
+		return;
+	}
 
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_stat_class_entry_ptr);
 
+		PHP_EV_ASSERT((self == NULL));
 		self = return_value; 
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pdOf|z!l",
-					&path, &path_len, &interval, &loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
 		self = getThis();
 	}
 
 }
 /* }}} */
 
-/* {{{ proto EvStat::__construct(string path, double interval, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvStat::__construct(string path, double interval, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvStat, __construct)
 {
 	php_ev_stat_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);

File tests/05_timer.phpt

 $fudge = 0.02;
 $id = 1;
 
-$loop = EvLoop::default_loop();
-$base = $loop->now();
-$prev = $loop->now();
+$base = ev_now();
+$prev = ev_now();
 
 for ($i = 1; $i <= 5; ++$i) {
 	$t = $i * $i * 1.735435336;
 	$t -= (int) $t;
 
-	$timer = new EvTimer($t, 0, $loop, function ($w, $r)
-		use (&$id, &$prev, $base, $loop, $i, $t, $fudge) {
-			$now = $loop->now();
+	$timer = new EvTimer($t, 0, function ($w, $r)
+		use (&$id, &$prev, $base, $i, $t, $fudge) {
+			$now = ev_now();
 
-			$loop->verify();
+			EvLoop::default_loop()->verify();
 
 			echo $now + $fudge >= $prev ? "" : "not ", "ok ", ++$id,
 				" # t0 $i $now + $fudge >= $prev\n";
 	$t = $i * $i * 1.375475771;
 	$t -= (int) $t;
 
-	$periodic = new EvPeriodic($base + $t, 0, NULL, $loop, function ($w, $r)
-		use (&$id, &$prev, $base, $loop, $i, $t) {
-			$now = $loop->now();
+	$periodic = new EvPeriodic($base + $t, 0, NULL, function ($w, $r)
+		use (&$id, &$prev, $base, $i, $t) {
+			$now = ev_now();
 
-			$loop->verify();
+			EvLoop::default_loop()->verify();
 
 			echo $now >= $prev ? "" : "not ", "ok ", ++$id,
 				" # p0 $i $now >= $prev\n";
 }
 
 echo "ok 1\n";
-$loop->run();
+ev_run();
 echo "ok 32\n";
 ?>
 --EXPECTF--

File tests/06_keepalive.phpt

 <?php 
 error_reporting(0);
 
-$loop = EvLoop::default_loop();
-
-$timer = new EvTimer(1, 0.3, $loop, function ($w, $r) {
+$timer = new EvTimer(1, 0.3, function ($w, $r) {
 	echo "ok 7\n";
 	$w->stop();
 });
 $timer->keepalive(1);
 
 echo "ok 1\n";
-$loop->run();
+ev_run();
 echo "ok 2\n";
 
 $timer->start();
 $timer->stop();
 $timer->start();
 
-$timer2 = new EvTimer(-1, 0, $loop, function ($w, $r) {
+$timer2 = new EvTimer(-1, 0, function ($w, $r) {
 	echo "ok 4\n";
 });
 $timer2->keepalive(0);
 
 echo "ok 3\n";
-$loop->run();
+ev_run();
 echo "ok 5\n";
 
 $timer->keepalive(1);
 
 echo "ok 6\n";
-$loop->run();
+ev_run();
 echo "ok 8\n";
 ?>
 --EXPECT--

File tests/07_stat.phpt

 <?php 
 error_reporting(0);
 
-$loop = EvLoop::default_loop();
-
 $fh = tempnam(__DIR__, 'ev_tmp_');
 
-$w = new EvStat("$fh", 0.1, $loop, function ($w, $r) use ($loop) {
+$w = new EvStat("$fh", 0.1, function ($w, $r) {
 	$prev = $w->prev();
 
 	echo "ok 5\n";
 	echo FALSE == $w->attr() ? "" : "not ", "ok 9\n";
 	echo FALSE == $w->stat() ? "" : "not ", "ok 10\n";
 
-   	$loop->break();
+   	ev_break();
 });
 $w->start();
 
 
-$t = new EvTimer(0.2, 0, $loop, function ($w, $r) use ($loop) {
+$t = new EvTimer(0.2, 0, function ($w, $r) {
 	echo "ok 2\n";
-	$loop->break();
+	ev_break();
 });
 $t->start();
 
 echo $w->stat() ? "" : "not ", "ok 1\n";
-$loop->run();
+ev_run();
 echo "ok 3\n";
 
 unlink($fh);
 
-$t = new EvTimer(0.2, 0, $loop, function ($w, $r) use ($loop) {
+$t = new EvTimer(0.2, 0, function ($w, $r) {
 	echo "ok 2\n";
-	$loop->break();
+	ev_break();
 });
 $t->start();
 
 echo "ok 4\n";
-$loop->run();
+ev_run();
 echo "ok 11\n";
 
 ?>

File tests/08_priority.phpt

 
 $loop = EvLoop::default_loop();
 
-$t0 = new EvTimer(-1, 0, $loop, function ($w, $r) use ($loop) { echo "ok 4\n"; });
-$t_ = new EvTimer(-1, 0, $loop, function ($w, $r) use ($loop) { echo "ok 5\n"; });
+$t0 = new EvTimer(-1, 0, function ($w, $r) { echo "ok 4\n"; });
+$t_ = new EvTimer(-1, 0, function ($w, $r) { echo "ok 5\n"; });
 $t_->priority = -1;
-$t1 = new EvTimer(-1, 0, $loop, function ($w, $r) use ($loop) { echo "ok 3\n"; });
+$t1 = new EvTimer(-1, 0, function ($w, $r) { echo "ok 3\n"; });
 $t1->priority = 1;
 
-$i2 = new EvIdle($loop, function ($w, $r) use ($loop) { echo $loop->iteration == 1 ? "" : "not ", "ok 2\n"; $w->stop(); });
+$i2 = new EvIdle(function ($w, $r) use ($loop) { echo $loop->iteration == 1 ? "" : "not ", "ok 2\n"; $w->stop(); });
 $i2->priority = 10;
-$i3 = new EvIdle($loop, function ($w, $r) use ($loop) { echo $loop->iteration == 3 ? "" : "not ", "ok 7\n"; $w->stop(); });
-$i1 = new EvIdle($loop, function ($w, $r) use ($loop) { echo $loop->iteration == 2 ? "" : "not ", "ok 6\n"; $w->stop(); });
+$i3 = new EvIdle(function ($w, $r) use ($loop) { echo $loop->iteration == 3 ? "" : "not ", "ok 7\n"; $w->stop(); });
+$i1 = new EvIdle(function ($w, $r) use ($loop) { echo $loop->iteration == 2 ? "" : "not ", "ok 6\n"; $w->stop(); });
 $i1->priority = 1;
-$i_ = new EvIdle($loop, function ($w, $r) use ($loop) { echo $loop->iteration == 4 ? "" : "not ", "ok 8\n"; $w->stop(); });
+$i_ = new EvIdle(function ($w, $r) use ($loop) { echo $loop->iteration == 4 ? "" : "not ", "ok 8\n"; $w->stop(); });
 $i_->priority = -1;
 
 $t0->start();
 $i_->start();
 
 echo "ok 1\n";
-$loop->run();
+ev_run();
 echo "ok 9\n";
 ?>
 --EXPECT--
 	zend_fcall_info_cache  fcc        = empty_fcall_info_cache;
 	long                   priority   = 0;
 
-	if (loop) { /* Factory */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddf|z!l",
-					&after, &repeat, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-	} else { /* Ctor */
-		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddOf|z!l",
-					&after, &repeat, &loop, ev_loop_class_entry_ptr, &fci, &fcc,
-					&data, &priority) == FAILURE) {
-			return;
-		}
-
-		self = getThis();
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddf|z!l",
+				&after, &repeat, &fci, &fcc,
+				&data, &priority) == FAILURE) {
+		return;
 	}
 
 	PHP_EV_CHECK_REPEAT(repeat);
 
-	if (!self) { /* Factory */
+	/* If loop is NULL, then we're in __construct() */
+	if (loop) {
 		PHP_EV_INIT_CLASS_OBJECT(return_value, ev_timer_class_entry_ptr);
+
+		PHP_EV_ASSERT((self == NULL));
 		self = return_value; 
+	} else {
+		loop = php_ev_default_loop(TSRMLS_C);
+		self = getThis();
 	}
 
 	o_self        = (php_ev_object *) zend_object_store_get_object(self TSRMLS_CC);
 /* }}} */
 
 
-/* {{{ proto EvTimer::__construct(double after, double repeat, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+/* {{{ proto EvTimer::__construct(double after, double repeat, callable callback[, mixed data = NULL[, int priority = 0]]) */
 PHP_METHOD(EvTimer, __construct)
 {
 	php_ev_timer_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL);
 /* {{{ php_ev_set_watcher()
  * Configure preallocated watcher of the specified type, initialize common watcher fields
  */
-void php_ev_set_watcher(ev_watcher *w, size_t size, zval *self, php_ev_loop *loop, const zend_fcall_info *pfci, const zend_fcall_info_cache *pfcc, zval *data, int priority TSRMLS_DC)
+void php_ev_set_watcher(ev_watcher *w, size_t size, zval *self, php_ev_loop *o_loop, const zend_fcall_info *pfci, const zend_fcall_info_cache *pfcc, zval *data, int priority TSRMLS_DC)
 {
-	ev_watcher *w_prev = loop->w;
-	loop->w = w;
+	/* Re-link the doubly linked list */
 
-	if (w_prev) {
-		php_ev_watcher_prev(w) = (void *) w_prev;
+	ev_watcher *w_next = o_loop->w;
+	o_loop->w          = w;
+
+	if (w_next) {
+		php_ev_watcher_next(w)      = (void *) w_next;
+		php_ev_watcher_prev(w_next) = (void *) w;
 	}
 
 	ev_init((ev_watcher *) w, (ZEND_FCI_INITIALIZED(*pfci) ? php_ev_watcher_callback : 0));
 
 	php_ev_watcher_self(w)  = self;
 	php_ev_watcher_data(w)  = data;
-	php_ev_watcher_loop(w)  = loop;
+	php_ev_watcher_loop(w)  = o_loop;
 	php_ev_watcher_flags(w) = PHP_EV_WATCHER_FLAG_KEEP_ALIVE;
 
 	PHP_EV_COPY_FCALL_INFO(php_ev_watcher_fci(w), php_ev_watcher_fcc(w), pfci, pfcc);
 /* {{{ php_ev_new_watcher()
  * Create watcher of the specified type, initialize common watcher fields
  */
-void *php_ev_new_watcher(size_t size, zval *self, php_ev_loop *loop, const zend_fcall_info *pfci, const zend_fcall_info_cache *pfcc, zval *data, int priority TSRMLS_DC)
+void *php_ev_new_watcher(size_t size, zval *self, php_ev_loop *o_loop, const zend_fcall_info *pfci, const zend_fcall_info_cache *pfcc, zval *data, int priority TSRMLS_DC)
 {
 	void *w = emalloc(size);
 	memset(w, 0, size);
 
-	php_ev_set_watcher((ev_watcher *)w, size, self, loop, pfci, pfcc, data, priority TSRMLS_CC);
+	php_ev_set_watcher((ev_watcher *) w, size, self, o_loop, pfci, pfcc, data, priority TSRMLS_CC);
 
 	return w;
 }
 /* {{{ proto EvLoop EvWatcher::get_loop(void) */
 PHP_METHOD(EvWatcher, get_loop)
 {
-	/*
-	 * RETURNING REFERENCES - 
-	 * Sara Goleman, ... p.71
-	 */
-
 	php_ev_object *o_self;
-	php_ev_loop *loop;
-	ev_watcher *w;
+	php_ev_loop   *o_loop;
+	ev_watcher    *w;
 
 	if (zend_parse_parameters_none() == FAILURE) {
 		return;
 
 	o_self = (php_ev_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
 	w      = PHP_EV_WATCHER_FETCH_FROM_OBJECT(o_self);
-	loop   = php_ev_watcher_loop(w);
+	o_loop   = php_ev_watcher_loop(w);
 
-	zval *zloop = (zval *) ev_userdata(loop->loop);
+	zval *zloop = (zval *) ev_userdata(o_loop->loop);
 
     if (!zloop) {
     	RETURN_NULL();
     }
 	RETVAL_ZVAL(zloop, 1, 0);
-
-#if 0
-	php_ev_object *o_loop;
-	Z_TYPE_P(return_value) = IS_OBJECT;
-	object_init_ex(return_value, ev_loop_class_entry_ptr);
-	Z_SET_REFCOUNT_P(return_value, 1);
-	Z_UNSET_ISREF_P(return_value);
-
-	o_loop = (php_ev_object *) zend_object_store_get_object(return_value TSRMLS_CC);
-	o_loop->ptr = (void *) loop;
-
-    if (loop->data) {
-		Z_ADDREF_P(loop->data);
-    }
-
-	if (loop->fci) {
-		if (ZEND_FCI_INITIALIZED(*loop->fci)) {
-			PHP_EV_FCI_ADDREF(loop->fci);
-		}
-	}
-#endif
-	
-#if 0 /* {{{ */
-	php_ev_object *o_self;
-	ev_watcher    *w;
-	zval          *loop;
-
-	if (zend_parse_parameters_none() == FAILURE) {
-		return;
-	}
-
-	o_self = (php_ev_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
-	w      = PHP_EV_WATCHER_FETCH_FROM_OBJECT(o_self);
-
-	loop   = php_ev_watcher_loop(w);
-
-    if (!loop) {
-    	RETURN_NULL();
-    }
-	RETVAL_ZVAL(loop, 1, 0);
-#endif /* }}} */
-
 }
 /* }}} */
 
 #define php_ev_watcher_thread_ctx(w) (((ev_watcher *) w)->thread_ctx)
 #define php_ev_watcher_type(w)       (((ev_watcher *) w)->type)
 #define php_ev_watcher_flags(w)      (((ev_watcher *) w)->e_flags)
+#define php_ev_watcher_next(w)       (((ev_watcher *) w)->e_next)
 #define php_ev_watcher_prev(w)       (((ev_watcher *) w)->e_prev)
 
 #define php_ev_watcher_loop_ptr(w)   (php_ev_watcher_loop(w)->loop)
         ev_ref(php_ev_watcher_loop(w)->loop);                                   \
     }
 
-#define PHP_EV_WATCHER_STOP(t, w)                         \
-    do {                                                  \
-        PHP_EV_WATCHER_REF(w);                            \
-        t ## _stop(php_ev_watcher_loop_ptr(w), (t *) w);  \
-    } while(0)
-
-#define PHP_EV_WATCHER_START(t, w)                        \
-    do {                                                  \
-        t ## _start(php_ev_watcher_loop_ptr(w), (t *) w); \
-        PHP_EV_WATCHER_UNREF(w);                          \
-    } while(0)
+#define PHP_EV_WATCHER_STOP(t, w)                             \
+    do {                                                      \
+        if (php_ev_watcher_loop(w)) {                         \
+            PHP_EV_WATCHER_REF(w);                            \
+            t ## _stop(php_ev_watcher_loop_ptr(w), (t *) w);  \
+        }                                                     \
+    } while (0)
+
+#define PHP_EV_WATCHER_START(t, w)                            \
+    do {                                                      \
+        if (php_ev_watcher_loop(w)) {                         \
+            t ## _start(php_ev_watcher_loop_ptr(w), (t *) w); \
+            PHP_EV_WATCHER_UNREF(w);                          \
+        }                                                     \
+    } while (0)
 
 /* Stop, ev_*_set() and start a watcher. Call it when need
  * to modify probably active watcher.
         if (is_active) {                                  \
             PHP_EV_WATCHER_START(t, w);                   \
         }                                                 \
-    } while(0)
+    } while (0)
 
 
 #define PHP_EV_CHECK_SIGNAL_CAN_START(w)                                           \
                     "Can't start signal watcher, signal %d already "               \
                     "registered in another loop", w->signum);                      \
         }                                                                          \
-    } while(0)
+    } while (0)
 
 #define PHP_EV_SIGNAL_START(w)              \
     do {                                    \
         PHP_EV_CHECK_SIGNAL_CAN_START(w);   \
         PHP_EV_WATCHER_START(ev_signal, w); \
-    } while(0)
+    } while (0)
 
 #define PHP_EV_SIGNAL_RESET(w, seta)             \
     do {                                         \
         ev_ ## signal ## _set seta;              \
         if (active)                              \
             PHP_EV_WATCHER_START(ev_signal, w);  \
-    } while(0)
+    } while (0)
 
 
 void php_ev_watcher_callback(EV_P_ ev_watcher *watcher, int revents);