源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
typedef struct tag_DLIST_NODE
{
struct tag_DLIST_NODE *prev;
struct tag_DLIST_NODE *next;
} DLIST_NODE;
typedef DLIST_NODE DLIST_HEAD;
#define dlist_init(e) \
(e)->prev = (e)->next = (e)
#define dlist_del(e) \
{(e)->prev->next = (e)->next; (e)->next->prev = (e)->prev; }
#define dlist_add(e, p) \
{ (e)->prev = (p); (e)->next = (p)->next; (p)->next = (e); (e)->next->prev = (e); }
#define dlist_insert(e, n) \
{ (e)->prev = (n)->prev; (e)->next = (n); (n)->prev->next = (e); (n)->prev = (e); }
#define dlist_isempty(e) \
( ( (e)->prev == (e) && (e)->next == (e) ) ? 1 : 0 )
#define dlist_entity(type, m, e) \
( (type *)((unsigned long)(e) - (unsigned long)&((type *)0)->m) )
#define dlist_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
#define dlist_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define ELEVATOR_NUM 4
#define ELEVATOR_FLOOR_NUM 10
typedef struct person_s
{
DLIST_NODE node;
int id;
int floor;
int tid;
int uptime;
int downtime;
}person_t;
typedef struct person_queue_s
{
DLIST_HEAD head;
int personCount;
pthread_mutex_t stMutex;
}person_queue_t;
typedef struct elevator_s
{
DLIST_HEAD head;
int id;
int floor;
int personCount;
int upCount;
int downCount;
int stime;
}elevator_t;
typedef struct time_node_s
{
DLIST_NODE node;
void *(*pFunc)(int);
int expire;
int passed;
}time_node_t;
typedef struct time_queue_s
{
DLIST_HEAD head;
int timeCount;
int runPerSeconds;
}time_queue_t;
static int id = 1;
person_queue_t *gstPersonQueue = NULL;
void time_proc(int expire)
{
person_t *person = NULL;
if(!gstPersonQueue)
{
return;
}
person = malloc(sizeof(person_t));
if(!person)
{
return;
}
person ->floor = expire;
person->id = id++;
//printf("[ID :%d %d]\n",person->id,expire);
pthread_mutex_lock(&gstPersonQueue->stMutex);
dlist_insert(&person->node,&gstPersonQueue->head);
gstPersonQueue->personCount++;
pthread_mutex_unlock(&gstPersonQueue->stMutex);
}
int add_timer(time_queue_t *pstQueue, void *pFunc, int ulTime)
{
time_node_t *pstNode = NULL;
pstNode = (time_node_t *)malloc(sizeof(time_node_t));
if(!pstNode)
{
return -1;
}
memset(pstNode,0,sizeof(time_node_t));
pstNode->pFunc = pFunc;
pstNode->expire = ulTime;
pstNode->passed = 0;
dlist_insert(&pstNode->node,&pstQueue->head);
pstQueue->timeCount += 1;
return 0;
}
void *start_timer(void *queue)
{
#if 0
int i = 1;
#endif
time_queue_t *pstQueue = NULL;
time_node_t *pstNode = NULL;
DLIST_NODE *pos = NULL ,*next = NULL;
pstQueue = (time_queue_t *)queue;
if(!pstQueue)
{
return NULL;
}
while(1)
{
usleep(1000000*pstQueue->runPerSeconds);
dlist_for_each_safe(pos,next,&pstQueue->head)
{
pstNode = dlist_entity(time_node_t,node,pos);
if((pstNode->passed + pstQueue->runPerSeconds) > pstNode->expire)
{
pstNode->pFunc(pstNode->expire);
pstNode->passed = 0;
}
pstNode->passed++;
}
#if 0
if(i++ == 11)
{
break;
}
#endif
}
return NULL;
}
void *elevator_run(void *data)
{
int upnum = 0;
int downnum = 0;
struct tm *p;
time_t time;
int up = 0;
person_t *person = NULL;
DLIST_NODE *pos = NULL, *next = NULL;
elevator_t *pstElevator=NULL;
pstElevator = (elevator_t *)(data);
printf("[ELEVATOR:%d] running!\n",pstElevator->id);
while(1)
{
pstElevator->stime++;
upnum = 0;
downnum = 0;
pos = NULL;
next = NULL;
person = NULL;
if(!gstPersonQueue)
{
continue;
}
/*up*/
if(pstElevator->floor == 1)
{
upnum = 0;
pthread_mutex_lock(&gstPersonQueue->stMutex);
if(gstPersonQueue->personCount)
{
/*up*/
//printf("UP-IDS");
dlist_for_each_safe(pos,next,&gstPersonQueue->head)
{
person = dlist_entity(person_t,node,pos);
dlist_del(pos);
dlist_insert(&person->node,&pstElevator->head);
gstPersonQueue->personCount--;
/*update elevator*/
pstElevator->upCount++;
pstElevator->personCount++;
upnum++;
//printf(" %d ",person->id);
}
//printf("\n");
time = (time_t)pstElevator->stime;
p=localtime(&time);
//printf("[Time%d:%d:%d][Elevator%d floor 1 up %d persons]\n",p->tm_hour,p->tm_min,p->tm_sec,pstElevator->id,upnum);
printf("[时间%d:%d:%d][电梯%d在1层上了%d个人]\n",p->tm_hour,p->tm_min,p->tm_sec,pstElevator->id,upnum);
}
pthread_mutex_unlock(&gstPersonQueue->stMutex);
if(pstElevator->personCount)
{
up = 1;
}
}
else
{
if(pstElevator->personCount)
{
downnum = 0;
//printf("Down-IDS");
dlist_for_each_safe(pos,next,&pstElevator->head)
{
person = dlist_entity(person_t,node,pos);
if(person->floor == pstElevator->floor)
{
downnum++;
dlist_del(pos);
//printf(" %d ",person->id);
free(person);
pstElevator->downCount++;
pstElevator->personCount--;
}
}
//printf("\n");
}
if(pstElevator->personCount == 0)
{
up = 0;
}
time = (time_t)pstElevator->stime;
p=localtime(&time);
printf("[时间%d:%d:%d][电梯%d在%d层下了%d个人]\n",p->tm_hour,p->tm_min,p->tm_sec,pstElevator->id,pstElevator->floor,downnum);
//printf("[Time%d:%d:%d][Elevator%d floor %d down %d persons]\n",p->tm_hour,p->tm_min,p->tm_sec,pstElevator->id,pstElevator->floor,downnum);
}
if(up)
{
if(pstElevator->floor < ELEVATOR_FLOOR_NUM)
{
pstElevator->floor++;
}
}
else
{
if(pstElevator->floor != 1)
{
pstElevator->floor--;
}
else
{
printf("[Elevator%d is on floor %d]\n",pstElevator->id,pstElevator->floor);
}
}
usleep(1000000);
}
}
int main(int argc, char **argv)
{
int ret = 0;
volatile int index = 0;
pthread_t tid[ELEVATOR_NUM+1];
time_t stime;
time_queue_t *pstTimeQueue = NULL;
person_queue_t *pstPersonQueue = NULL;
elevator_t *pstElevator = NULL;
pstTimeQueue = (time_queue_t *)malloc(sizeof(time_queue_t));
if(!pstTimeQueue)
{
ret = -1;
goto Error;
}
memset(pstTimeQueue,0,sizeof(time_queue_t));
pstPersonQueue = (person_queue_t *)malloc(sizeof(person_queue_t));
if(!pstPersonQueue)
{
ret = -1;
goto Error;
}
memset(pstPersonQueue,0,sizeof(person_queue_t));
pstElevator = (elevator_t *)malloc(sizeof(elevator_t)*ELEVATOR_NUM);
if(!pstElevator)
{
ret = -1;
goto Error;
}
memset(pstElevator,0,sizeof(elevator_t)*ELEVATOR_NUM);
/*init*/
dlist_init(&pstTimeQueue->head);
pstTimeQueue->runPerSeconds = 1;
dlist_init(&pstPersonQueue->head);
pthread_mutex_init(&pstPersonQueue->stMutex,NULL);
stime = time(NULL);
for(index=0;index<ELEVATOR_NUM;index++)
{
dlist_init(&pstElevator[index].head);
pstElevator[index].stime=stime;
pstElevator[index].floor=1;
pstElevator[index].id=index+1;
}
gstPersonQueue = pstPersonQueue;
/*add time*/
for(index=2;index<=ELEVATOR_FLOOR_NUM;index++)
{
ret = add_timer(pstTimeQueue,time_proc,index);
if(ret)
{
goto Error;
}
}
for(index=0; index< ELEVATOR_NUM+1; index++)
{
if(index >0 )
{
ret = pthread_create(&tid[index],NULL,elevator_run,(void *)(&pstElevator[index-1]));
}
else
{
ret = pthread_create(&tid[index],NULL,start_timer,(void *)pstTimeQueue);
}
if(ret)
{
goto Error;
}
}
while(1);
Error:
if(pstTimeQueue)
{
free(pstTimeQueue);
}
if(pstTimeQueue)
{
free(pstPersonQueue);
}
if(pstElevator)
{
free(pstElevator);
}
return ret;
}
运行结果:
[ELEVATOR:3] running!
[Elevator3 is on floor 1]
[ELEVATOR:4] running!
[Elevator4 is on floor 1]
[ELEVATOR:2] running!
[Elevator2 is on floor 1]
[ELEVATOR:1] running!
[Elevator1 is on floor 1]
[Elevator3 is on floor 1]
[Elevator4 is on floor 1]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[Elevator3 is on floor 1]
[Elevator4 is on floor 1]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[Elevator3 is on floor 1]
[Elevator4 is on floor 1]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[时间9:33:27][电梯3在1层上了1个人]
[Elevator4 is on floor 1]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[时间9:33:28][电梯3在2层下了1个人]
[时间9:33:28][电梯4在1层上了1个人]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[时间9:33:29][电梯3在1层上了3个人]
[时间9:33:29][电梯4在2层下了0个人]
[Elevator2 is on floor 1]
[Elevator1 is on floor 1]
[时间9:33:30][电梯3在2层下了1个人]
[时间9:33:30][电梯4在3层下了1个人]
[时间9:33:30][电梯2在1层上了1个人]
[Elevator1 is on floor 1]
[时间9:33:31][电梯3在3层下了0个人]
[时间9:33:31][电梯4在2层下了0个人]
[时间9:33:31][电梯2在2层下了0个人]
[时间9:33:31][电梯1在1层上了3个人]
[时间9:33:32][电梯3在4层下了1个人]
[时间9:33:32][电梯4在1层上了2个人]
[时间9:33:32][电梯2在3层下了0个人]
[时间9:33:32][电梯1在2层下了1个人]
[时间9:33:33][电梯3在3层下了0个人]
[时间9:33:33][电梯4在2层下了0个人]
[时间9:33:33][电梯2在4层下了0个人]
[时间9:33:33][电梯1在3层下了1个人]
[时间9:33:34][电梯3在2层下了0个人]
[时间9:33:34][电梯4在3层下了0个人]
[时间9:33:34][电梯2在5层下了1个人]
[时间9:33:34][电梯1在4层下了0个人]
[时间9:33:35][电梯3在1层上了11个人]
[时间9:33:35][电梯4在4层下了0个人]
[时间9:33:35][电梯2在4层下了0个人]
[时间9:33:35][电梯1在5层下了0个人]
[时间9:33:36][电梯3在2层下了2个人]
[时间9:33:36][电梯4在5层下了0个人]
[时间9:33:36][电梯2在3层下了0个人]
[时间9:33:36][电梯1在6层下了1个人]
[时间9:33:37][电梯3在3层下了1个人]
[时间9:33:37][电梯4在6层下了0个人]
[时间9:33:37][电梯2在2层下了0个人]
[时间9:33:37][电梯1在5层下了0个人]
[时间9:33:38][电梯3在4层下了1个人]
[时间9:33:38][电梯4在7层下了1个人]
[时间9:33:38][电梯2在1层上了5个人]
[时间9:33:38][电梯1在4层下了0个人]
附件:
[elevator.c][1]