cvs: embed /php-irssi ext-irssi.c /php-irssi/examples timeout.php
[email protected] ("Wez Furlong") Sat, 01 Feb 2003 13:51:34 -0000
| Newsgroups | php.embed.cvs |
|---|---|
| Message-ID | <cvswez1044107494@cvsserver> |
--wez1044107494
Content-Type: text/plain
wez Sat Feb 1 08:51:34 2003 EDT
Added files:
/embed/php-irssi/examples timeout.php
Modified files:
/embed/php-irssi ext-irssi.c
Log:
Implement timeout API.
See examples/timeout.php for a demonstration.
--wez1044107494
Content-Type: text/plain
Content-Disposition: attachment; filename="wez-20030201085134.txt"
Index: embed/php-irssi/ext-irssi.c
diff -u embed/php-irssi/ext-irssi.c:1.6 embed/php-irssi/ext-irssi.c:1.7
--- embed/php-irssi/ext-irssi.c:1.6 Fri Jan 31 23:46:56 2003
+++ embed/php-irssi/ext-irssi.c Sat Feb 1 08:51:34 2003
@@ -14,7 +14,7 @@
+----------------------------------------------------------------------+
| Author: Wez Furlong <[email protected]> |
+----------------------------------------------------------------------+
- $Id: ext-irssi.c,v 1.6 2003/02/01 04:46:56 wez Exp $
+ $Id: ext-irssi.c,v 1.7 2003/02/01 13:51:34 wez Exp $
*/
#include "php-irssi.h"
#include "php-signals-list.h" /* generated by php during make */
@@ -28,8 +28,17 @@
struct sig_record {
zval *handler;
- int signal_id;
zval *arg;
+ enum { SIG_REC_TYPE_SIGNAL, SIG_REC_TYPE_TIMEOUT } type;
+ union {
+ struct {
+ int signal_id;
+ } sig;
+ struct {
+ int tag;
+ int one_shot;
+ } timeout;
+ } v;
};
HashTable *bound_signals;
@@ -51,6 +60,73 @@
/* Signals */
+static char *signal_hash_key(char *signame, zval *callback TSRMLS_DC)
+{
+ char *key = NULL;
+
+ if (Z_TYPE_P(callback) == IS_ARRAY) {
+ zval **obj = NULL, **func = NULL;
+
+ zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&obj);
+ zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&func);
+
+ if (obj == NULL || func == NULL) {
+ return NULL;
+ }
+
+ convert_to_string_ex(func);
+
+ if (Z_TYPE_PP(obj) == IS_OBJECT) {
+ spprintf(&key, 0, "%s@%d@%s", signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func));
+ return key;
+ }
+
+ /* class name */
+ convert_to_string_ex(obj);
+ spprintf(&key, 0, "%s@%s@%s", signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func));
+ return key;
+ }
+ if (Z_TYPE_P(callback) == IS_STRING) {
+ spprintf(&key, 0, "%s@%s", signame, Z_STRVAL_P(callback));
+ return key;
+ }
+ return NULL;
+}
+
+static char *timeout_hash_key(int tag, zval *callback TSRMLS_DC)
+{
+ char *key = NULL;
+
+ if (Z_TYPE_P(callback) == IS_ARRAY) {
+ zval **obj = NULL, **func = NULL;
+
+ zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&obj);
+ zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&func);
+
+ if (obj == NULL || func == NULL) {
+ return NULL;
+ }
+
+ convert_to_string_ex(func);
+
+ if (Z_TYPE_PP(obj) == IS_OBJECT) {
+ spprintf(&key, 0, "%d@%d@%s", tag, (*obj)->value.obj.handle, Z_STRVAL_PP(func));
+ return key;
+ }
+
+ /* class name */
+ convert_to_string_ex(obj);
+ spprintf(&key, 0, "%d@%s@%s", tag, Z_STRVAL_PP(obj), Z_STRVAL_PP(func));
+ return key;
+ }
+ if (Z_TYPE_P(callback) == IS_STRING) {
+ spprintf(&key, 0, "%d@%s", tag, Z_STRVAL_P(callback));
+ return key;
+ }
+ return NULL;
+}
+
+
static inline struct php_irssi_signal_args *sigid_to_args(int sigid)
{
int i;
@@ -174,39 +250,113 @@
}
}
-static char * signal_hash_key(char *signame, zval *callback TSRMLS_DC)
+static int php_source_event(struct sig_record *rec)
{
- char *key = NULL;
+ zval **zargs[1] = { NULL };
+ zval *arg = NULL, *retval = NULL;
+ int argc = 0, i;
+
+ if (rec->arg) {
+ MAKE_STD_ZVAL(arg);
+ *arg = *(rec->arg);
+ zval_copy_ctor(arg);
+
+ zargs[argc++] = &arg;
+ }
+
+ call_user_function_ex(EG(function_table),
+ NULL,
+ rec->handler,
+ &retval,
+ argc,
+ zargs,
+ 0, NULL TSRMLS_CC);
- if (Z_TYPE_P(callback) == IS_ARRAY) {
- zval **obj = NULL, **func = NULL;
+ if (retval)
+ zval_ptr_dtor(&retval);
- zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&obj);
- zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&func);
+ if (arg) {
+ FREE_ZVAL(arg);
+ }
- if (obj == NULL || func == NULL) {
- return NULL;
- }
+ if (rec->v.timeout.one_shot) {
+ char *sighash = timeout_hash_key(rec->v.timeout.tag, rec->handler TSRMLS_CC);
+ zend_hash_del(bound_signals, sighash, strlen(sighash)+1);
+ efree(sighash);
+ }
+
+ return 1;
+}
- convert_to_string_ex(func);
-
- if (Z_TYPE_PP(obj) == IS_OBJECT) {
- spprintf(&key, 0, "%s@%d@%s", signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func));
- return key;
- }
-
- /* class name */
- convert_to_string_ex(obj);
- spprintf(&key, 0, "%s@%s@%s", signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func));
- return key;
+PHP_FUNCTION(irssi_timeout_remove)
+{
+ char *signame;
+ long signame_len;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ &signame, &signame_len)) {
+ return;
}
- if (Z_TYPE_P(callback) == IS_STRING) {
- spprintf(&key, 0, "%s@%s", signame, Z_STRVAL_P(callback));
- return key;
+
+ zend_hash_del(bound_signals, signame, signame_len+1);
+}
+
+/* proto string irssi_timeout_add(long msecsinterval, mixed callback, [mixed arg, [bool oneshot]])
+ Requests that callback be called every msecsinterval. */
+PHP_FUNCTION(irssi_timeout_add)
+{
+ zval *sigarg = NULL, *funcname, *tmp;
+ long msecsinterval;
+ int sigid;
+ struct sig_record *rec;
+ char *sighash = NULL;
+ zend_bool oneshot = 0;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|z!b",
+ &msecsinterval,
+ &funcname,
+ &sigarg,
+ &oneshot
+ )) {
+ return;
+ }
+
+ rec = emalloc(sizeof(struct sig_record));
+
+ MAKE_STD_ZVAL(rec->handler);
+ *(rec->handler) = *funcname;
+ zval_copy_ctor(rec->handler);
+
+ if (sigarg) {
+ MAKE_STD_ZVAL(rec->arg);
+ *(rec->arg) = *sigarg;
+ zval_copy_ctor(rec->arg);
+ } else {
+ rec->arg = NULL;
+ }
+
+ rec->type = SIG_REC_TYPE_TIMEOUT;
+ rec->v.timeout.tag = g_timeout_add(msecsinterval, (GSourceFunc)php_source_event, rec);
+ rec->v.timeout.one_shot = oneshot;
+
+ sighash = timeout_hash_key(rec->v.timeout.tag, rec->handler TSRMLS_CC);
+
+ if (sighash) {
+ zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL);
+
+ /* no need to dup it */
+ RETVAL_STRING(sighash, 0);
+
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash timeout handler");
+ zend_hash_next_index_insert(bound_signals, &rec, sizeof(rec), NULL);
+
+ RETVAL_NULL();
}
- return NULL;
}
+
+
/* proto void irssi_signal_add(string signalname, mixed callback, [long priority, mixed sigarg])
Binds a function to a signal. priority is one of the IRSSI_PRIORITY_XXX constants */
PHP_FUNCTION(irssi_signal_add)
@@ -234,6 +384,7 @@
}
rec = emalloc(sizeof(struct sig_record));
+ rec->type = SIG_REC_TYPE_SIGNAL;
sigid = signal_get_uniq_id(signame);
@@ -241,7 +392,7 @@
*(rec->handler) = *funcname;
zval_copy_ctor(rec->handler);
- rec->signal_id = sigid;
+ rec->v.sig.signal_id = sigid;
if (sigarg) {
MAKE_STD_ZVAL(rec->arg);
@@ -367,8 +518,6 @@
RETURN_FALSE;
}
- signal_remove_id((*rec)->signal_id, sig_func, rec);
-
zend_hash_del(bound_signals, sighash, strlen(sighash)+1);
efree(sighash);
@@ -379,6 +528,12 @@
static void sig_rec_dtor(void *pDest)
{
struct sig_record *rec = *(struct sig_record **)pDest;
+
+ if (rec->type == SIG_REC_TYPE_SIGNAL) {
+ signal_remove_id(rec->v.sig.signal_id, sig_func, rec);
+ } else {
+ g_source_remove(rec->v.timeout.tag);
+ }
if (rec->handler) {
zval_ptr_dtor(&rec->handler);
@@ -459,6 +614,8 @@
PHP_FE(irssi_signal_emit, NULL)
PHP_FE(irssi_signal_remove, NULL)
PHP_FE(irssi_signal_get_arg, NULL)
+ PHP_FE(irssi_timeout_add, NULL)
+ PHP_FE(irssi_timeout_remove, NULL)
NULL, NULL, NULL
};
Index: embed/php-irssi/examples/timeout.php
+++ embed/php-irssi/examples/timeout.php
<?php
/* $Id: timeout.php,v 1.1 2003/02/01 13:51:34 wez Exp $
*
* Timeouts.
*
* This sample demonstrates how to request that irssi call back into
* your PHP script at regular intervals.
* Timeouts are specified in millisecond intervals, and it is worth noting
* that the timing of the intervals can never be 100% accurate.
* It should be "good enough" for most purposes.
*
* Just like any callback made from irssi, you should not hang around for
* too long; long delays can cause irssi to drop network connections to
* your chatnets.
*/
/* This snippet shows how to trigger an event at 1 second intervals.
* The event will continue to occur for all time. */
function ticktock()
{
static $tick = true;
if ($tick)
echo "TICK!\n";
else
echo "TOCK!\n";
$tick = !$tick;
}
$tag = irssi_timeout_add(1000, "ticktock");
/* Surely, after a while that ticktock will become annoying, so this
* next snippet shows how to create a one-shot timeout that will
* turn off the tick tock and never be called again.
*/
function shut_that_thing_off($tag)
{
irssi_timeout_remove($tag);
echo "No more ticking!";
}
irssi_timeout_add(5000, "shut_that_thing_off", $tag, true);
?>
--wez1044107494--