Commits

Ruslan Osmanov  committed 7870a6a

Add: EvSignal class

  • Participants
  • Parent commits fed3901

Comments (0)

Files changed (8)

 #if EV_PERIODIC_ENABLE
 zend_class_entry *ev_periodic_class_entry_ptr;
 #endif
+#if EV_SIGNAL_ENABLE
+zend_class_entry *ev_signal_class_entry_ptr;
+#endif
 
 static HashTable classes;
 static HashTable php_ev_properties;
 #if EV_PERIODIC_ENABLE
 static HashTable php_ev_periodic_properties;
 #endif
+#if EV_SIGNAL_ENABLE
+static HashTable php_ev_signal_properties;
+#endif
 
 static zend_object_handlers ev_object_handlers;
 
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ php_ev_signal_free_storage() */
+static void php_ev_signal_free_storage(void *object TSRMLS_DC)
+{
+	php_ev_object *obj_ptr = (php_ev_object *) object;
+
+	PHP_EV_ASSERT(obj_ptr->ptr);
+	ev_signal *ptr = (ev_signal *) obj_ptr->ptr;
+
+	/* Free base class members */
+	php_ev_watcher_free_storage((ev_watcher *) ptr TSRMLS_CC);
+
+	/* Free common Ev object members and the object itself */
+	php_ev_object_free_storage(object TSRMLS_CC);
+}
+/* }}} */
+#endif
+
 /* {{{ php_ev_register_object 
  * Is called AFTER php_ev_object_new() */
 zend_object_value php_ev_register_object(zend_class_entry *ce, php_ev_object *intern TSRMLS_DC)
 		/* EvPeriodic */
 	 	func_free_storage = php_ev_periodic_free_storage;
 #endif
+#if EV_SIGNAL_ENABLE
+	} else if (instanceof_function(ce, ev_signal_class_entry_ptr TSRMLS_CC)) {
+		/* EvSignal*/
+	 	func_free_storage = php_ev_signal_free_storage;
+#endif
 	} else {
 	 	func_free_storage = php_ev_object_free_storage;
 	}
 	/* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+	/* {{{ EvSignal*/
+	PHP_EV_REGISTER_CLASS_ENTRY_EX("EvSignal", ev_signal_class_entry_ptr, ev_signal_class_entry_functions, ev_watcher_class_entry_ptr);
+	ce = ev_signal_class_entry_ptr;
+	zend_hash_init(&php_ev_signal_properties, 0, NULL, NULL, 1);
+	PHP_EV_ADD_CLASS_PROPERTIES(&php_ev_signal_properties, ev_signal_property_entries);
+	zend_hash_merge(&php_ev_signal_properties, &php_ev_watcher_properties, NULL, NULL, sizeof(php_ev_prop_handler), 0);
+	PHP_EV_DECL_CLASS_PROPERTIES(ce, ev_signal_property_entry_info);
+	zend_hash_add(&classes, ce->name, ce->name_length + 1, &php_ev_signal_properties, sizeof(php_ev_signal_properties), NULL);
+	/* }}} */
+#endif
+
+
+
 }
 /* }}} */
 
 #if EV_PERIODIC_ENABLE
 	zend_hash_destroy(&php_ev_periodic_properties);
 #endif
+#if EV_SIGNAL_ENABLE
+	zend_hash_destroy(&php_ev_signal_properties);
+#endif
 	zend_hash_destroy(&classes);
 
 	return SUCCESS;
 #if EV_PERIODIC_ENABLE
 # include "periodic.c"
 #endif
+#if EV_SIGNAL_ENABLE
+# include "signal.c";
+#endif
 
 #endif /* HAVE_EV */
 
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ EvSignal*/
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_signal, 0, 0, 3)
+	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)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ev_signal_set, 0, 0, 1)
+	ZEND_ARG_INFO(0, signum)
+ZEND_END_ARG_INFO();
+/* }}} */
+#endif
+
 /* ARGINFO }}} */
 
 
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ ev_signal_class_entry_functions */
+const zend_function_entry ev_signal_class_entry_functions[] = {
+	PHP_ME(EvSignal, __construct, arginfo_ev_signal,     ZEND_ACC_PUBLIC  | ZEND_ACC_CTOR)
+	PHP_ME(EvSignal, set,         arginfo_ev_signal_set, ZEND_ACC_PUBLIC)
+
+	{ NULL, NULL, NULL }
+};
+/* }}} */
+#endif
+
 /*
  * Local variables:
  * tab-width: 4
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ EvSignal */
+PHP_METHOD(EvSignal, __construct);
+PHP_METHOD(EvSignal, set);
+/* }}} */
+#endif
+
 #endif /* PHP_EV_FE_H */
 
 /* 
 #endif
 
 #define PHP_EV_COPY_FCALL_INFO(pfci_dst, pfcc_dst, pfci, pfcc)                                  \
-{                                                                                               \
     if (ZEND_FCI_INITIALIZED(*pfci)) {                                                          \
         pfci_dst = (zend_fcall_info *) safe_emalloc(1, sizeof(zend_fcall_info), 0);             \
         pfcc_dst = (zend_fcall_info_cache *) safe_emalloc(1, sizeof(zend_fcall_info_cache), 0); \
         pfci_dst = NULL;                                                                        \
         pfcc_dst = NULL;                                                                        \
     }                                                                                           \
-}
 
 #define PHP_EV_FREE_FCALL_INFO(pfci, pfcc)       \
-{                                                \
     if (pfci && pfcc) {                          \
         efree(pfcc);                             \
                                                  \
         }                                        \
         efree(pfci);                             \
     }                                            \
-}
 
 #define PHP_EV_LOOP_OBJECT_FETCH_FROM_OBJECT(obj) (obj ? (php_ev_loop *) obj->ptr : NULL)
 #define PHP_EV_WATCHER_FETCH_FROM_OBJECT(o)       ((ev_watcher *) o->ptr)
     EV_P = PHP_EV_LOOP_FETCH_FROM_OBJECT(ev_obj) /* no ';' */
 
 #define PHP_EV_CHECK_PENDING_WATCHER(w)              \
-{                                                    \
     if (ev_is_pending(w)) {                          \
         php_error_docref(NULL TSRMLS_CC, E_ERROR,    \
                 "Failed modifying pending watcher"); \
         return;                                      \
     }                                                \
-}
 
 #define PHP_EV_EXIT_LOOP(__loop) ev_break((__loop), EVBREAK_ALL)
 
     } while (0)
 
 #define PHP_EV_CHECK_REPEAT(repeat)                                                 \
-{                                                                                   \
     if (repeat < 0.) {                                                              \
         php_error_docref(NULL TSRMLS_CC, E_ERROR, # repeat " value must be >= 0."); \
         return;                                                                     \
     }                                                                               \
-}
+
 #define PHP_EV_CHECK_REPEAT_RET(repeat, ret)                                        \
-{                                                                                   \
     if (repeat < 0.) {                                                              \
         php_error_docref(NULL TSRMLS_CC, E_ERROR, # repeat " value must be >= 0."); \
         return (ret);                                                               \
     }                                                                               \
-}
+
+#define PHP_EV_CHECK_SIGNUM(num)                                     \
+    if ((num) < 0) {                                                 \
+        php_error_docref(NULL TSRMLS_CC, E_ERROR, "invalid signum"); \
+        return;                                                      \
+    }                                                                \
+
 
 #endif /* PHP_EV_MACROS_H*/
 
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ EvSignal property handlers */
+
+/* {{{ ev_signal_prop_signum_read */
+static int ev_signal_prop_signum_read(php_ev_object *obj, zval **retval TSRMLS_DC)
+{
+	PHP_EV_ASSERT(obj->ptr);
+
+	ev_signal *signal_watcher = (ev_signal *) PHP_EV_WATCHER_FETCH_FROM_OBJECT(obj);
+
+	MAKE_STD_ZVAL(*retval);
+	ZVAL_LONG(*retval, signal_watcher->signum);
+
+	return SUCCESS;
+}
+/* }}} */
+
+/* }}} */
+#endif
+
 /* {{{ ev_loop_property_entries[] */
 const php_ev_property_entry ev_loop_property_entries[] = {
 	{"data",            sizeof("data")            - 1, ev_loop_prop_data_read,            ev_loop_prop_data_write},
 /* }}} */
 #endif
 
+#if EV_SIGNAL_ENABLE
+/* {{{ ev_signal_property_entries[] */
+const php_ev_property_entry ev_signal_property_entries[] = {
+	{"signum", sizeof("signum") - 1, ev_signal_prop_signum_read, NULL},
+    {NULL, 0, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ ev_signal_property_entry_info[] */
+const zend_property_info ev_signal_property_entry_info[] = {
+	{ZEND_ACC_PUBLIC, "signum", sizeof("signum") - 1, -1, 0, NULL, 0, NULL},
+	{0, NULL, 0, -1, 0, NULL, 0, NULL},
+};
+/* }}} */
+#endif
+
 /*
  * Local variables:
  * tab-width: 4
 extern const zend_function_entry ev_io_class_entry_functions[];
 extern const zend_function_entry ev_timer_class_entry_functions[];
 extern const zend_function_entry ev_periodic_class_entry_functions[];
+extern const zend_function_entry ev_signal_class_entry_functions[];
 
 extern const php_ev_property_entry ev_test_property_entries[];
 extern const php_ev_property_entry ev_loop_property_entries[];
 extern const php_ev_property_entry ev_io_property_entries[];
 extern const php_ev_property_entry ev_timer_property_entries[];
 extern const php_ev_property_entry ev_periodic_property_entries[];
+extern const php_ev_property_entry ev_signal_property_entries[];
 
 extern const zend_property_info ev_test_property_entry_info[];
 extern const zend_property_info ev_loop_property_entry_info[];
 extern const zend_property_info ev_io_property_entry_info[];
 extern const zend_property_info ev_timer_property_entry_info[];
 extern const zend_property_info ev_periodic_property_entry_info[];
+extern const zend_property_info ev_signal_property_entry_info[];
 
 #endif /* PHP_EV_PRIV_H */
 
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2012 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Ruslan Osmanov <osmanov@php.net>                             |
+   +----------------------------------------------------------------------+
+*/
+#include "watcher.h"
+
+/* {{{ proto EvSignal::__construct(int signum, EvLoop loop, callable callback[, mixed data = NULL[, int priority = 0]]) */
+PHP_METHOD(EvSignal, __construct)
+{
+	long           signum;
+	zval          *self;
+	php_ev_object *o_self;
+	php_ev_object *o_loop;
+	ev_signal     *signal_watcher;
+
+	zval                  *loop;
+	zval                  *data       = NULL;
+	zend_fcall_info        fci        = empty_fcall_info;
+	zend_fcall_info_cache  fcc        = empty_fcall_info_cache;
+	long                   priority   = 0;
+
+	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;
+	}
+
+	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);
+	signal_watcher = (ev_signal *) php_ev_new_watcher(sizeof(ev_signal), self,
+			PHP_EV_LOOP_OBJECT_FETCH_FROM_OBJECT(o_loop),
+			&fci, &fcc, data, priority TSRMLS_CC);
+
+	signal_watcher->type = EV_SIGNAL;
+	
+	ev_signal_set(signal_watcher, signum);
+
+	o_self->ptr = (void *) signal_watcher;
+}
+/* }}} */
+
+/* {{{ proto void EvSignal::set(int signum) */
+PHP_METHOD(EvSignal, set)
+{
+	long       signum;
+	ev_signal *signal_watcher;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
+				&signum) == FAILURE) {
+		return;
+	}
+
+	PHP_EV_CHECK_SIGNUM(signum);
+
+	signal_watcher = (ev_signal *) PHP_EV_WATCHER_FETCH_FROM_THIS();
+
+	PHP_EV_SIGNAL_RESET(signal_watcher, (signal_watcher, signum));
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4 sts=4
+ */
         }                                                 \
     } while(0)
 
+
+#define PHP_EV_CHECK_SIGNAL_CAN_START(w)                                           \
+    do {                                                                           \
+        /* Pulled this part from EV module of Perl */                              \
+        if (signals [(w)->signum - 1].loop                                         \
+                && signals [(w)->signum - 1].loop != php_ev_watcher_loop_ptr(w)) { \
+            php_error_docref(NULL TSRMLS_CC, E_WARNING,                            \
+                    "Can't start signal watcher, signal %d already "               \
+                    "registered in another loop", w->signum);                      \
+        }                                                                          \
+    } 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)
+
+#define PHP_EV_SIGNAL_RESET(w, seta)             \
+    do {                                         \
+        int active = ev_is_active(w);            \
+        if (active)                              \
+            PHP_EV_WATCHER_STOP(ev_signal, w);   \
+        ev_ ## signal ## _set seta;              \
+        if (active)                              \
+            PHP_EV_WATCHER_START(ev_signal, w);  \
+    } while(0)
+
+
 void php_ev_watcher_callback(EV_P_ ev_watcher *watcher, int revents);
 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);