Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include "playlist.h"

static Channel *reqs;

Req*
reqalloc(void)
{
        Req *r;

        if(reqs == nil)
                reqs = chancreate(sizeof(Req*), 256);
        if(r = nbrecvp(reqs))
                return r;
        r = malloc(sizeof(Req));
        return r;
}

void
reqfree(Req *r)
{
        if(!nbsendp(reqs, r))
                free(r);
}

Wmsg
waitmsg(Worker *w, Channel *q)
{
        Wmsg m;

        sendp(q, w);
        recv(w->eventc, &m);
        return m;
}

int
sendmsg(Channel *q, Wmsg *m)
{
        Worker *w;

        while(w = nbrecvp(q)){
                /* Test for markerdom (see bcastmsg) */
                if(w->eventc){
                        send(w->eventc, m);
                        return 1;
                }
                sendp(q, w);    /* put back */
        }
        return 0;
}

void
bcastmsg(Channel *q, Wmsg *m)
{
        Worker *w, marker;
        void *a;

        a = m->arg;
        /*
         * Use a marker to mark the end of the queue.
         * This prevents workers from getting the
         * broadcast and putting themselves back on the
         * queue before the broadcast has finished
         */
        marker.eventc = nil;    /* Only markers have eventc == nil */
        sendp(q, &marker);
        while((w = recvp(q)) != &marker){
                if(w->eventc == nil){
                        /* somebody else's marker, put it back */
                        sendp(q, w);
                }else{
                        if(a) m->arg = strdup(a);
                        send(w->eventc, m);
                }
        }
        free(a);
        m->arg = nil;
}

void
readbuf(Req *r, void *s, long n)
{
        r->ofcall.count = r->ifcall.count;
        if(r->ifcall.offset >= n){
                r->ofcall.count = 0;
                return;
        }
        if(r->ifcall.offset+r->ofcall.count > n)
                r->ofcall.count = n - r->ifcall.offset;
        memmove(r->ofcall.data, (char*)s+r->ifcall.offset, r->ofcall.count);
}

void
readstr(Req *r, char *s)
{
        readbuf(r, s, strlen(s));
}