#include <stdio.h>
#include "pt.h"
#include "printqsim.h"

typedef void (*funcp)();

typedef struct {
  Job **b;
  int head;
  int tail;
  Gsem njobs;
  Gsem nslots;
  funcp *f;
  void **a;
} Buffer;
  
void initialize_v(Spq *s)
{
  Buffer *b;

  b = (Buffer *) malloc(sizeof(Buffer));
  b->b = (Job **) malloc(sizeof(Job *)*s->bufsize);
  b->head = 0;
  b->tail = 0;
  b->njobs = make_gsem(0);
  b->nslots = make_gsem(s->bufsize);
  b->f = (funcp *) malloc(sizeof(funcp)*(s->nusers+s->nprinters));
  b->a = (void **) malloc(sizeof(void *)*(s->nusers+s->nprinters));
  s->v = (void *) b;
}

void submit_job_cont(s)
Spq *s;
{
  Buffer *b;

  b = (Buffer *) s->v;

  b->b[b->head] = s->j;
  b->head = (b->head + 1) % s->bufsize;
  gsem_V(b->njobs);
  pt_yield(b->f[s->id], b->a[s->id]);
}
      
void submit_job(s, j, f, a)
Spq *s;
Job *j;
void (*f)();
void *a;
{
  Buffer *b;

  b = (Buffer *) s->v;

  s->j = j;
  b->f[s->id] = f;
  b->a[s->id] = a;

  gsem_P(b->nslots, submit_job_cont, s);
}


void get_print_job_cont(s)
Spq *s;
{
  Buffer *b;

  b = (Buffer *) s->v;

  s->j = b->b[b->tail];
  b->tail = (b->tail + 1) % s->bufsize;
  gsem_V(b->nslots);
  pt_yield(b->f[s->id+s->nusers], b->a[s->id+s->nusers]);
}

get_print_job(s, f, a)
Spq *s;
void (*f)();
void *a;
{
  Buffer *b;

  b = (Buffer *) s->v;
  b->f[s->id+s->nusers] = f;
  b->a[s->id+s->nusers] = a;
  gsem_P(b->njobs, get_print_job_cont, s);
}


