The finite state machine

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include "relayer.h"

#define TTY1 "/dev/tty11"
#define TTY2 "/dev/tty12"
#define TTY3 "/dev/tty10"
#define TTY4 "/dev/tty9"

int main()
{
 int fd1,fd2,fd3,fd4;
 int job1,job2;
 struct rel_stat_st st;
 
 fd1 = open(TTY1,O_RDWR);
 if(fd1 < 0)
 {
  perror("open()");
  exit(1);
 }
 write(fd1,"TTY1\n",5);

 fd2 = open(TTY2,O_RDWR|O_NONBLOCK);
    if(fd2 < 0)
    {
        perror("open()");
        exit(1);
    }
 write(fd2,"TTY2\n",5);

 job1 = rel_addjob(fd1,fd2);
 if(job1 < 0)
 {
  fprintf(stderr,"rel_addjob():%s\n",strerror(-job1));
  exit(1);
 }

 fd3 = open(TTY3,O_RDWR);
    if(fd3 < 0)
    {
        perror("open()");
        exit(1);
    }
    write(fd3,"TTY3\n",5);

    fd4 = open(TTY4,O_RDWR|O_NONBLOCK);
    if(fd4 < 0)
    {
        perror("open()");
        exit(1);
    }
    write(fd4,"TTY4\n",5);

 job2 = rel_addjob(fd3,fd4);
    if(job2 < 0)
    {
        fprintf(stderr,"rel_addjob():%s\n",strerror(-job2));
        exit(1);
    }
// 忙等(判断假错)
 while(1)
 {
  rel_statjob(job1,&st);
  printf("job1:1->2(%lld)\t2->1(%lld)\n",st.count12,st.count21);
  rel_statjob(job2,&st);
  printf("job2:1->2(%lld)\t2->1(%lld)\n",st.count12,st.count21);
  puts("");
  sleep(1);
 }

 close(fd1);
 close(fd2);
 close(fd3);
 close(fd4);

 exit(0);
}

 

-----------------------------------------------------------------------------------------------

// 负载均衡器(serviver)
//查寻法
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#include "relayer.h"

#define BUFSIZE 1024

enum
{
 STATE_R=1,
 STATE_W,
 STATE_Ex,
 STATE_T
};

// 状态机的状态
struct rel_fsa_st
{
 int state;
 int sfd,dfd;
 int64_t count;//成功写入的字节数
 char buf[BUFSIZE];
 int len,pos;
 char *errstr;
};

//
struct rel_job_st
{
 int fd1,fd2;
 int job_state; 
 pthread_mutex_t mut_job_state;
 pthread_cond_t cond_job_state;
 struct rel_fsa_st fsa12,fsa21;
 int fd1_save,fd2_save;
// struct timeval start,end;
};

static struct rel_job_st *rel_job[REL_JOBMAX];
static pthread_mutex_t mut_rel_job = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;

static void fetch_stat_unlocked(int id,struct rel_stat_st *statp);

static void fsa_driver(struct rel_fsa_st *fsa)
{
 int ret;
  
 switch(fsa->state)
 {
  case STATE_R:
   fsa->len = read(fsa->sfd,fsa->buf,BUFSIZE);
   if(fsa->len == 0)
    fsa->state = STATE_T;
   else if(fsa->len < 0)
    {
     if(errno == EAGAIN)
      fsa->state = STATE_R;
     else
     {
      fsa->state = STATE_Ex;
      fsa->errstr = "read()";
     }
    }
    else
    {
     fsa->pos = 0;
     fsa->state = STATE_W;
    }
   break;

  case STATE_W:
   ret = write(fsa->dfd,fsa->buf+fsa->pos,fsa->len);
   if(ret < 0)
   {
    if(errno == EAGAIN)
     fsa->state = STATE_W;
    else
    {
     fsa->errstr = "write()";
     fsa->state = STATE_Ex;
    }
   
   } 
   else
   {
    fsa->pos += ret;
    fsa->len -= ret;
    fsa->count += ret;
    if(fsa->len == 0)
     fsa->state = STATE_R;
    else
     fsa->state = STATE_W; 
   }
   break;

  case STATE_Ex:
   perror(fsa->errstr);
   fsa->state = STATE_T;
   break;

  case STATE_T:/*do nothing*/
   break;

  default:
   abort();
   break;
 }


}


static void *thr_relayer(void *unused)
{
 int i;
 while(1)
 {
  pthread_mutex_lock(&mut_rel_job);
  for(i = 0 ;i < REL_JOBMAX; i++)
  {
   if(rel_job[i] != NULL)
   {
    pthread_mutex_lock(&rel_job[i]->mut_job_state);
    if(rel_job[i]->job_state==STATE_RUNNING)
    { 
     fsa_driver(&rel_job[i]->fsa12);
     fsa_driver(&rel_job[i]->fsa21);
     if(rel_job[i]->fsa12.state == STATE_T && \
      rel_job[i]->fsa21.state == STATE_T)
     {
      rel_job[i]->job_state = STATE_OVER;
      pthread_cond_broadcast(&rel_job[i]->cond_job_state);
     }
    }
    pthread_mutex_unlock(&rel_job[i]->mut_job_state);
   }
  }
  pthread_mutex_unlock(&mut_rel_job);
 }
}

static void module_load(void)
{
 int err;
 pthread_t tid_relayer; 

 err = pthread_create(&tid_relayer,NULL,thr_relayer,NULL);
 if(err)
 {
  fprintf(stderr,"pthread_create():%s\n",strerror(err));
  exit(1);
 }
}

static int get_free_pos_unlocked(void)
{
 int i;
 for(i = 0 ;i < REL_JOBMAX; i++)
  if(rel_job[i] == NULL)
   return i;
 return -1;
}

int rel_addjob(int fd1,int fd2)
{
 int pos;
 struct rel_job_st *me;

 pthread_once(&init_once,module_load);

 if(fd1 < 0 || fd2 < 0)
  return -EINVAL;

 me = malloc(sizeof(*me));
 if(me == NULL)
  return -ENOMEM;

 me->fd1 = fd1;
 me->fd2 = fd2;
 me->job_state = STATE_RUNNING;
 pthread_mutex_init(&me->mut_job_state,NULL);
 pthread_cond_init(&me->cond_job_state,NULL); 
 
 me->fd1_save = fcntl(me->fd1,F_GETFL);
 fcntl(me->fd1,F_SETFL,me->fd1_save|O_NONBLOCK);
 me->fd2_save = fcntl(me->fd2,F_GETFL);
    fcntl(me->fd2,F_SETFL,me->fd2_save|O_NONBLOCK);

 me->fsa12.sfd = me->fd1;
 me->fsa12.dfd = me->fd2;
 me->fsa12.state = STATE_R;
 me->fsa12.count = 0;
 
 me->fsa21.sfd = me->fd2;
 me->fsa21.dfd = me->fd1;
 me->fsa21.state = STATE_R;
 me->fsa21.count = 0;

 pthread_mutex_lock(&mut_rel_job);
 pos = get_free_pos_unlocked();
 if(pos < 0)
 {
  pthread_mutex_unlock(&mut_rel_job);
  fcntl(me->fd1,F_SETFL,me->fd1_save);
  fcntl(me->fd2,F_SETFL,me->fd2_save);
  free(me);
  return -ENOSPC;
 }
 rel_job[pos] = me;
 pthread_mutex_unlock(&mut_rel_job);
 return pos;
}


int rel_canceljob(int id)
{
 pthread_mutex_lock(&mut_rel_job);
 if(id < 0 || id >= REL_JOBMAX || rel_job[id] == NULL)
 { 
  pthread_mutex_unlock(&mut_rel_job);
  return -EINVAL;
 }
 pthread_mutex_lock(&rel_job[id]->mut_job_state);
 if(rel_job[id]->job_state == STATE_CANCELED)
 {
  pthread_mutex_unlock(&rel_job[id]->mut_job_state);
  pthread_mutex_unlock(&mut_rel_job);
        return  -ECANCELED;
 }
 if(rel_job[id]->job_state == STATE_OVER)
    {
  pthread_mutex_unlock(&rel_job[id]->mut_job_state);
        pthread_mutex_unlock(&mut_rel_job);
        return  -EBUSY;
    }

 rel_job[id]->job_state = STATE_CANCELED ;
 pthread_cond_broadcast(&rel_job[id]->cond_job_state);
 pthread_mutex_unlock(&rel_job[id]->mut_job_state);
 pthread_mutex_unlock(&mut_rel_job); 
 return 0;
}

int rel_waitjob(int id,struct rel_stat_st *statp)
{
 pthread_mutex_lock(&mut_rel_job);
    if(id < 0 || id >= REL_JOBMAX || rel_job[id] == NULL)
    {
        pthread_mutex_unlock(&mut_rel_job);
        return -EINVAL;
    }

 pthread_mutex_lock(&rel_job[id]->mut_job_state);
 while(rel_job[id]->job_state == STATE_RUNNING)
   pthread_cond_wait(&rel_job[id]->cond_job_state,&rel_job[id]->mut_job_state);
  
 if(statp != NULL)
  fetch_stat_unlocked(id ,statp);
 pthread_mutex_unlock(&rel_job[id]->mut_job_state);
 pthread_mutex_destroy(&rel_job[id]->mut_job_state);
 pthread_cond_destroy(&rel_job[id]->cond_job_state);
 fcntl(rel_job[id]->fd1,F_SETFL,rel_job[id]->fd1_save); 
 fcntl(rel_job[id]->fd2,F_SETFL,rel_job[id]->fd2_save); 
 free(rel_job[id]);
 rel_job[id] = NULL;
 pthread_mutex_unlock(&mut_rel_job);
 return 0;
}

static void fetch_stat_unlocked(int id,struct rel_stat_st *statp)
{
 statp->fd1 = rel_job[id]->fd1;
 statp->fd2 = rel_job[id]->fd2;
 statp->state = rel_job[id]->job_state;
 statp->count12 = rel_job[id]->fsa12.count;
 statp->count21 = rel_job[id]->fsa21.count;
}

int rel_statjob(int id ,struct rel_stat_st *statp)
{
 pthread_mutex_lock(&mut_rel_job);
    if(id < 0 || id >= REL_JOBMAX || rel_job[id] == NULL)
    {
        pthread_mutex_unlock(&mut_rel_job);
        return -EINVAL;
    }
 fetch_stat_unlocked(id,statp); 
 pthread_mutex_unlock(&mut_rel_job);
 return 0;
}

--------------------------------------------------------------------------------------------

 

#ifndef RELAYER_H__
#define RELAYER_H__

#define REL_JOBMAX 10000


//任务状态
enum
{
 STATE_RUNNING=1,
 STATE_CANCELED, //被取消
 STATE_OVER
};
//user's structure (提取结构体的一部分),半封装形式
struct rel_stat_st
{
 int fd1,fd2;
 int state;
 int64_t count12,count21;
// struct timeval start,end;
};


int rel_addjob(int fd1,int fd2);
/*
 * return : >= 0  成功,返回任务标识
 *    == -ENOMEM 失败,内存分配失败 
 *    == -ENOSPC 失败,任务数组已满
 *    == -EINVAL 失败,参数非法 
 * */ 

int rel_canceljob(int );
/*
 * return : == 0  成功,指定任务已取消
 *    == -EINVAL 失败,参数非法
 *    == -EBUSY 失败,任务已正常终止 
 *    == -ECANCELED 失败,任务早已被取消
 * */

int rel_waitjob(int,struct rel_stat_st *);
/* 
 * return : == 0  成功,指定任务已终止并返回状态
 *    == -EINVAL 失败,参数非法
 * */
//指定任务瞬间状态
int rel_statjob(int,struct rel_stat_st *);
/*
 * return : == 0  成功,指定任务状态已返回
 *    == -EINVAL 失败,参数非法
 * */

 

#endif

 


 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值