Пример #1
0
/**
 * Initializes a new player.
 * The player is placed in the queue of available players.
 */
struct player *player_init(struct player *p, struct game *g, double x, double y,
                           double w, double h, uint32_t score, uint8_t data) {
	cpVect all[4] = {cpv(0,0), cpv(0,h), cpv(w,h), cpv(w,0)};
	cpBody *body = cpBodyInit(&p->body, 10, cpMomentForBox(10, w, h));
	if (!body) {
		ERR_ERRNO();
		return 0;
	}
	cpBodySetPos(body, cpv(x,y));
	//cpShape *shape = cpPolyShapeNew(body,4,all,cpv((p->l+p->r)/2.0,(p->b+p->t)/2.0));
	cpShape *shape = cpPolyShapeInit(&p->shape, body, 4, all, cpv(0, 0));
	if (!shape) {
		ERR_ERRNO();
		cpBodyDestroy(body);
		return 0;
	}
	shape->data = p;
	shape->collision_type = PLAYER;
	if (linkedlist_add_last(g->p_q, p)) {
		ERR_TRACE();
		cpBodyDestroy(body);
		cpShapeDestroy(shape);
		return 0;
	}
	p->x = x;
	p->y = y;
	p->node = g->p_q->last;
	return p;
}
Пример #2
0
static void tea_thread_stop(int tid)
{
  THREAD_WORK *tw;
  int r;

  /* wait until we have exclusive access right on ttable */
  DBG("[tea] Thread %d killing scheduled.", tid);
  pthreadex_lock_get_exclusive_n(&ttable_lock, "kill-thread");

  /* going to kill thread */
  tw = ttable[tid];
  pthreadex_lock_release();

  if(tw != NULL)
  {
    DBG("[tea] Killing thread %d.", tid);

    /* consider it dead */
    ttable[tid] = NULL;

    /* allow thread to do the cleanup */
    DBG2("[tea] Approve cleanup...");
    pthreadex_flag_up(&(tw->cleanup_do));

    while((r = pthread_cancel(tw->pthread_id)) != 0 && errno == EINTR)
    {
      DBG("[tea] Cancel EINTR; repeating pthread_cancel() on %d", tid);
      errno = 0;
    }
    if(r != 0)
      ERR_ERRNO("[tea] Cannot cancel thread %d", tid);

    /* kill thread */
    while((r = pthread_detach(tw->pthread_id)) != 0 && errno == EINTR)
    {
      DBG("[tea] Detach EINTR; repeating pthread_detach() on  %d", tid);
      errno = 0;
    }
    if(r != 0)
      ERR_ERRNO("[tea] Cannot detach thread %d", tid);

    /* wait cleanup finishes */
    DBG2("[tea] Wait cleanup termination...");
    pthreadex_flag_wait(&(tw->cleanup_done));

    DBG("[tea] THREAD %d KILLED!", tid);

    /* destroy flags && free mem */
    pthreadex_flag_destroy(&(tw->mwaiting));
    pthreadex_flag_destroy(&(tw->cleanup_do));
    pthreadex_flag_destroy(&(tw->cleanup_done));
    free(tw);
  } else
    ERR("[tea] Thread %d does not exist or died voluntarely.", tid);
}
Пример #3
0
/**
 * Add the item at the specified location.
 */
int linkedlist_add(linkedlist *l, void *v, int loc) {
	if (loc == l->len) {
		return linkedlist_add_last(l,v);
	} else if (loc == 0) {
		return linkedlist_add_first(l,v);
	} else if (loc > l->len || loc < 0) {
		return 0;
	}
	linkedlist_node *n = malloc(sizeof(linkedlist_node));
	if (!n) {
		ERR_ERRNO();
		return -1;
	}
	n->data = v;
	int a;
	linkedlist_node *next = l->first;
	for (a = 0;a < loc;a++)
		next = next->next;
	n->prev = next->prev;
	n->next = next;
	next->prev->next = n;
	next->prev = n;
	l->len++;
	return 0;
}
Пример #4
0
struct wall *wall_create(struct game *g, double l, double r, double b, double t) {
	struct wall *wa = calloc(1, sizeof(struct wall));
	if (!wa) {
		ERR_ERRNO();
		return 0;
	}
	return wall_init(wa, g, l, r, b, t);
}
Пример #5
0
/**
 * Creates a new player by allocating memory and then initializing it. 
 * \sa player_init
 */
struct player *player_create(struct game *g, double x, double y, double w,
                             double h, uint32_t score, uint8_t data) {
	struct player *p = calloc(1, sizeof(struct player));
	if (!p) {
		ERR_ERRNO();
		return 0;
	}
	return player_init(p, g, x, y, w, h, score, data);
}
Пример #6
0
/**
 * Create a bubble that will bounce around the screen.
 * \param g The game in which to create the bubble.
 * \param x The x location of the bubble.
 * \param y The y location of the bubble.
 * \param v_x The x velocity of the bubble.
 * \param v_y The y velocity of the bubble.
 * \param r The radius of the bubble.
 * \param l The bubble's life. 
 */
struct bubble *bubble_create(double x, double y, double v_x, double v_y,
                             double r, uint8_t l) {
	struct bubble *b = calloc(1, sizeof(struct bubble));
	if (!b) {
		ERR_ERRNO();
		return 0;
	}
	return bubble_init(b, x, y, v_x, v_y, r, l);
}
Пример #7
0
/**
 * Create the linked list
 */
linkedlist *linkedlist_create() {
	linkedlist *cur = malloc(sizeof(linkedlist));
	if (!cur) {
		ERR_ERRNO();
		return 0;
	}
	cur->len = 0;
	cur->first = 0;
	cur->last = 0;
	return cur;
}
Пример #8
0
/**
 * Create a duplicate list
 */
linkedlist *linkedlist_clone(linkedlist *l) {
	linkedlist *ll = malloc(sizeof(linkedlist));
	if (!ll) {
		ERR_ERRNO();
		return 0;
	}
	linkedlist_node *cur = l->first;
	for (;cur;cur = cur->next) {
		linkedlist_add_last(ll,cur->data);
	}
	return ll;
}
Пример #9
0
/**
 * Initialize a bubble that will bounce around. 
 * \param b The bubble to initialize.
 * \param x The x location of the bubble.
 * \param y The y location of the bubble.
 * \param v_x The x velocity of the bubble.
 * \param v_y The y velocity of the bubble.
 * \param r The radius of the bubble.
 * \param l The bubble's life. 
 */
struct bubble *bubble_init(struct bubble *b, double x, double y, double v_x,
                           double v_y, double r, uint8_t l) {
	cpBody *body = cpBodyInit(&b->body, r,
	                          cpMomentForCircle(r, 0, r, cpv(0, 0)));
	if (!body) {
		ERR_ERRNO();
		return 0;
	}
	cpShape *shape = cpCircleShapeInit(&b->shape, body, r, cpv(0,0));
	if (!shape) {
		cpBodyDestroy(body);
		ERR_ERRNO();
		return 0;
	}
	cpBodySetVel(body, cpv(v_x, v_y));
	cpBodySetPos(body, cpv(x, y));
	shape->e = 1.0;
	shape->data = b;
	shape->collision_type = BUBBLE;
	b->l = l;
	return b;
}
Пример #10
0
int linkedlist_add_last(linkedlist *l, void *v) {
	linkedlist_node *n = malloc(sizeof(linkedlist_node));
	if (!n) {
		ERR_ERRNO();
		return -1;
	}
	n->next = 0;
	n->data = v;
	n->prev = l->last;
	if (l->last)
		l->last->next = n;
	else
		l->first = n;
	l->last = n;
	l->len++;
	return 0;
}
Пример #11
0
int tea_thread_msg_send(LN_CONTEXT *lnc, TEA_MSG *m, int delay)
{
  static int pivot_id = 0;
  int tid = 0;

  if(delay > 0 || !lnc)
  {
    if(delay > 0)
    {
      /* calculate when */
      if(clock_gettime(CLOCK_REALTIME, &m->w) < 0)
      {
        ERR_ERRNO("Cannot read CLOCK_REALTIME.");
        return -1;
      }
      DBG2("[tea] Now is %ld.%09ld", m->w.tv_sec, m->w.tv_nsec);
      m->w.tv_nsec += (delay % 1000) * 1000000;;
      m->w.tv_sec  += (delay / 1000) * 1000000;
      if(m->w.tv_nsec > 1000000000)
      {
        m->w.tv_sec  += m->w.tv_nsec / 1000000000;
        m->w.tv_nsec %= 1000000000;
      }
    } else {
      /* normal people send directly */
      m->w.tv_nsec = 0;
      m->w.tv_sec  = 0;
    }
    DBG("[tea] Packet queued and delayed until %ld.%09ld secs", m->w.tv_sec, m->w.tv_nsec);

    /* search sender and insert msg into its queue */
    pthreadex_lock_get_shared(&ttable_lock);
    tid = pivot_id < 0 ? 0 : pivot_id;
    do {
      if(++tid >= cfg.maxthreads)
        tid = 0;
      if(ttable[tid] && ttable[tid]->to->sender)
      {
        /* insert into queue in correct order */
        DBG2("[tea] Selected sender thread %d.", tid);
        mqueue_insert_delayed(ttable[tid]->mqueue, m);
        pthreadex_flag_up(&(ttable[tid]->mwaiting));
        m = NULL;
        break;
      }
    } while(tid != pivot_id);
    pivot_id = tid;
    pthreadex_lock_release();
  }

  /* if msg was not queued, then send it directly */
  if(m)
  {
    if(lnc)
    {
      DBG("[tea] Packet is being sent now");
      ln_send_packet(lnc, m->b, m->s, &m->dest);
    } else
      WRN("[tea] Cannot send message (lnc neither sender thread available).");
  }

  return 0;
}
Пример #12
0
static void tea_thread_new(int tid, TEA_OBJECT *to, SNODE *command)
{
  THREAD_WORK *tw = NULL;
  TEA_OBJCFG *ocline;
  HASH_ITER hi;
  HASH_NODE *hn;
  int fatal = 0;

  DBG("[tea] Creating thread %d.", tid);
  if((tw = calloc(1, sizeof(THREAD_WORK))) == NULL)
    FAT("Cannot alloc THREAD_WORK struct for thread %d.", tid);

  tw->id         = tid;
  tw->pthread_id = 0;
  tw->to         = to;
  tw->options    = hash_copy(command->command.thc.to->options);

  /* check methods */
  if(tw->to->listener || tw->to->sender)
    tw->mqueue = mqueue_create();
  pthreadex_flag_init(&(tw->mwaiting), 0);
  pthreadex_flag_name(&(tw->mwaiting), "mwaiting");
  pthreadex_flag_init(&(tw->cleanup_do), 0);
  pthreadex_flag_name(&(tw->cleanup_do), "cleanup_do");
  pthreadex_flag_init(&(tw->cleanup_done), 0);
  pthreadex_flag_name(&(tw->cleanup_done), "cleanup_done");

  /* global thread initialization here */
  if(tw->to->global_init && !tw->to->initialized)
  {
    tw->to->initialized = -1;
    tw->to->global_init();
  }

  /* make space for thread data */
  if((tw->data = calloc(1, to->datasize)) == NULL)
    FAT("%d:%s: No memory for thread data.", command->line, to->name);

  /* check config params */
  if(to->cparams)
  {
    /* check only allowed params are defined */
    for(hn = hash_iter_first(&hi, command->command.thc.to->options);
        !hash_iter_finished(&hi);
        hn = hash_iter_next(&hi))
    {
      /* iterate all allowed params and stop if (1) declared  */
      /* parameter hn->key is found in allowed paramter list, */
      /* or (2) stop if there is not moar allowed params      */
      for(ocline = to->cparams;
          ocline->name && strcasecmp(hn->key, ocline->name);
          ocline++)
        ;
      if(!ocline->name)
        FAT("%d:%s: Parameter %s not allowed here.", command->line, to->name, hn->key);
    }

    /* set params (apply configuration) */
    for(ocline = to->cparams; ocline->name; ocline++)
    {
      SNODE *val;

      /* get configured value (or set default value if not specified) */
      val = tea_thread_param_value_get(tw->options, ocline->name);

      /* check if parameter is optional */
      if(!val && ocline->needed)
        FAT("%d:%s: Parameter %s is mandatory.", command->line, to->name, ocline->name);

      /* set value */
      if(tea_thread_param_value_set(tw, ocline, val))
        FAT("%d:%s: Cannot set parameter %s.", command->line, to->name, ocline->name);
    }
  } else {
    if(command->command.thc.to->options
    || command->command.thc.to->options->nentries > 0)
      FAT("%d:%s: Parameters not allowed for this type of thread.", command->line, to->name);
  }

  /* once configuration applied, launch thread configuration routine */
  if(tw->to->configure
  && tw->to->configure(tw, command, 1))
      FAT("%d:%s: Thread configuration failed.", command->line, to->name);

  /* add thread to the list */
  pthreadex_lock_get_exclusive_n(&ttable_lock, "install-thread");
  DBG("[tea] Installing thread %d.", tid);

  /* build threads */
  if(ttable[tid])
    FATAL_ERROR("Thread slot %d is used already.", tid);
  ttable[tid] = tw;

  /* launch thread */
  if(pthread_create(&(tw->pthread_id), NULL, tea_thread, tw) != 0)
  {
    ERR_ERRNO("Error creating thread %d", tid);
    FATAL_ERROR("Fatal error happened during thread creation.");
  }

termination:
  if(fatal && tw)
  {
    if(ttable[tid] == tw)
      ttable[tid] = NULL;
    if(tw->mqueue)
      mqueue_destroy(tw->mqueue);
    pthreadex_flag_destroy(&(tw->mwaiting));
    pthreadex_flag_destroy(&(tw->cleanup_do));
    pthreadex_flag_destroy(&(tw->cleanup_done));
    free(tw);
  }

  pthreadex_lock_release();
  
  if(!fatal)
    return;

  FAT("Aborting.");
}