Scheme_Object *scheme_place_send(int argc, Scheme_Object *args[]) { if (argc == 2) { Scheme_Object *mso; Scheme_Place_Bi_Channel *ch; if (SAME_TYPE(SCHEME_TYPE(args[0]), scheme_place_type)) { ch = (Scheme_Place_Bi_Channel *) ((Scheme_Place *) args[0])->channel; } else if (SAME_TYPE(SCHEME_TYPE(args[0]), scheme_place_bi_channel_type)) { ch = (Scheme_Place_Bi_Channel *) args[0]; } else { ch = NULL; scheme_wrong_type("place-channel-send", "place-channel", 0, argc, args); } { void *msg_memory = NULL; mso = scheme_places_serialize(args[1], &msg_memory); scheme_place_async_send((Scheme_Place_Async_Channel *) ch->sendch, mso, msg_memory); } } else { scheme_wrong_count_m("place-channel-send", 2, 2, argc, args, 0); } return scheme_true; }
static void scheme_place_async_send(Scheme_Place_Async_Channel *ch, Scheme_Object *uo) { void *msg_memory = NULL; Scheme_Object *o; int cnt; o = scheme_places_serialize(uo, &msg_memory); mzrt_mutex_lock(ch->lock); { cnt = ch->count; if (ch->count == ch->size) { /* GROW QUEUE */ Scheme_Object **new_msgs; void **new_msg_memory; new_msgs = GC_master_malloc(sizeof(Scheme_Object*) * ch->size * 2); new_msg_memory = GC_master_malloc(sizeof(void*) * ch->size * 2); if (ch->out < ch->in) { memcpy(new_msgs, ch->msgs + ch->out, sizeof(Scheme_Object *) * (ch->in - ch->out)); memcpy(new_msg_memory, ch->msg_memory + ch->out, sizeof(void*) * (ch->in - ch->out)); } else { int s1 = (ch->size - ch->out); memcpy(new_msgs, ch->msgs + ch->out, sizeof(Scheme_Object *) * s1); memcpy(new_msgs + s1, ch->msgs, sizeof(Scheme_Object *) * ch->in); memcpy(new_msg_memory, ch->msg_memory + ch->out, sizeof(void*) * s1); memcpy(new_msg_memory + s1, ch->msg_memory, sizeof(void*) * ch->in); } ch->msgs = new_msgs; ch->msg_memory = new_msg_memory; ch->in = ch->size; ch->out = 0; ch->size *= 2; } ch->msgs[ch->in] = o; ch->msg_memory[ch->in] = msg_memory; ++ch->count; ch->in = (++ch->in % ch->size); } mzrt_mutex_unlock(ch->lock); if (!cnt && ch->wakeup_signal) { /*wake up possibly sleeping receiver */ scheme_signal_received_at(ch->wakeup_signal); } }