/* * call-seq: * mq.notify = signal => signal * * Registers the notification request to deliver a given +signal+ * to the current process when message is received. * If +signal+ is +nil+, it will unregister and disable the notification * request to allow other processes to register a request. * If +signal+ is +false+, it will register a no-op notification request * which will prevent other processes from registering a notification. * If +signal+ is an +IO+ object, it will spawn a thread upon the * arrival of the next message and write one "\\0" byte to the file * descriptor belonging to that IO object. * Only one process may have a notification request for a queue * at a time, Errno::EBUSY will be raised if there is already * a notification request registration for the queue. * * Notifications are only fired once and processes must reregister * for subsequent notifications. * * For readers of the mq_notify(3) manpage, passing +false+ * is equivalent to SIGEV_NONE, and passing +nil+ is equivalent * of passing a NULL notification pointer to mq_notify(3). */ static VALUE setnotify(VALUE self, VALUE arg) { struct posix_mq *mq = get(self, 1); struct sigevent not; struct sigevent * notification = ¬ VALUE rv = arg; notify_cleanup(self); not.sigev_notify = SIGEV_SIGNAL; switch (TYPE(arg)) { case T_FALSE: not.sigev_notify = SIGEV_NONE; break; case T_NIL: notification = NULL; break; case T_FIXNUM: not.sigev_signo = NUM2INT(arg); break; case T_SYMBOL: case T_STRING: not.sigev_signo = lookup_sig(arg); rv = INT2NUM(not.sigev_signo); break; default: rb_raise(rb_eArgError, "must be a signal or nil"); } my_mq_notify(mq->des, notification); return rv; }
lily_sig *lily_build_ensure_sig(lily_symtab *symtab, lily_class *cls, int entries_to_use, lily_sig **siglist, int offset) { lily_sig fake_sig; fake_sig.cls = cls; fake_sig.template_pos = 0; fake_sig.siglist = siglist + offset; fake_sig.siglist_size = entries_to_use; fake_sig.flags = 0; fake_sig.next = NULL; /* The reason it's done like this is purely to save memory. There's no point in creating a new signature if it already exists (since that just means the new one has to be destroyed). */ lily_sig *result_sig = lookup_sig(symtab, &fake_sig); if (result_sig == NULL) { lily_sig *new_sig = lily_malloc(sizeof(lily_sig)); lily_sig **new_siglist = lily_malloc(entries_to_use * sizeof(lily_sig *)); if (new_sig == NULL || new_siglist == NULL) { lily_free(new_sig); lily_free(new_siglist); lily_raise_nomem(symtab->raiser); } memcpy(new_sig, &fake_sig, sizeof(lily_sig)); memcpy(new_siglist, siglist + offset, sizeof(lily_sig *) * entries_to_use); new_sig->siglist = new_siglist; new_sig->next = symtab->root_sig; symtab->root_sig = new_sig; finalize_sig(new_sig); result_sig = new_sig; } return result_sig; }