⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scheduler.c++

📁 好东东。linux下面的文件节点、文件状态的变化监听代码
💻 C++
字号:
//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.//  //  This program is free software; you can redistribute it and/or modify it//  under the terms of version 2 of the GNU General Public License as//  published by the Free Software Foundation.////  This program is distributed in the hope that it would be useful, but//  WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any//  license provided herein, whether implied or otherwise, is limited to//  this program in accordance with the express provisions of the GNU//  General Public License.  Patent licenses, if any, provided herein do not//  apply to combinations of this program with other product or programs, or//  any other product whatsoever.  This program is distributed without any//  warranty that the program is delivered free of the rightful claim of any//  third person by way of infringement or the like.  See the GNU General//  Public License for more details.////  You should have received a copy of the GNU General Public License along//  with this program; if not, write the Free Software Foundation, Inc., 59//  Temple Place - Suite 330, Boston MA 02111-1307, USA.#include "Scheduler.h"#include <assert.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <sys/param.h>#include "Log.h"#include "timeval.h"//  Define a bunch of class-global variables.Scheduler::IOTypeInfo	 Scheduler::read(&FDInfo::read);Scheduler::IOTypeInfo	 Scheduler::write(&FDInfo::write);unsigned int		 Scheduler::nfds;Scheduler::FDInfo	*Scheduler::fdinfo;unsigned int		 Scheduler::nfdinfo_alloc;unsigned int		 Scheduler::ntasks;Scheduler::TimedProc	 Scheduler::recurring_proc;void			*Scheduler::recurring_closure;timeval			 Scheduler::next_task_time;timeval			 Scheduler::recurring_interval;Scheduler::onetime_task	*Scheduler::first_task;bool			 Scheduler::running;////////////////////////////////////////////////////////////////////////////////  One time task codevoidScheduler::install_onetime_task(const timeval& when,				TimedProc proc, void *closure){    onetime_task **fp = &first_task;    while (*fp && (*fp)->when < when)	fp = &(*fp)->next;    onetime_task *nt = new onetime_task;    nt->next = *fp;    *fp = nt;    nt->when = when;    nt->proc = proc;    nt->closure = closure;    ntasks++;}voidScheduler::remove_onetime_task(TimedProc proc, void *closure){    onetime_task *p, **pp = &first_task;    while ((p = *pp) != NULL)    {        if (p->proc == proc && p->closure == closure)	{   *pp = p->next;	    delete p;	    ntasks--;	    break;	}    	pp = &p->next;    }}////////////////////////////////////////////////////////////////////////////////  Recurring task codevoidScheduler::install_recurring_task(const timeval& interval,				  TimedProc proc, void *closure){    timeval now;    assert(!recurring_proc);    assert(proc);    assert(interval.tv_sec >= 0);    assert(interval.tv_usec >= 0 && interval.tv_usec < 1000000);    assert(interval.tv_sec || interval.tv_usec);    recurring_proc = proc;    recurring_closure = closure;    recurring_interval = interval;    ntasks++;    (void) gettimeofday(&now, NULL);    next_task_time = now + interval;}voidScheduler::remove_recurring_task(TimedProc proc, void *closure){    assert(proc == recurring_proc);    assert(closure == recurring_closure);    recurring_proc = NULL;    recurring_closure = closure;    timerclear(&recurring_interval);    ntasks--;}//  do_tasks activates all timer based tasks.  It also sets//  next_task_time to the absolute time when it should next be//  invoked.voidScheduler::do_tasks(){    if (ntasks)    {        timeval now;	(void) gettimeofday(&now, NULL);	if (recurring_proc && now >= next_task_time)	{	    // Time for the next task.            (*recurring_proc)(recurring_closure);	    next_task_time += recurring_interval;	    // If the clock has jumped ahead or we've gotten too far behind,	    // postpone the next task.	    if (next_task_time < now)		next_task_time = now + recurring_interval;	}	else	{   timeval time_left = next_task_time - now;	    if (recurring_interval < time_left)	    {		// More time left than we started with -- clock must have		// run backward.  Reset next_task_time to sane value.		next_task_time = now + recurring_interval;	    }	}	while (first_task && first_task->when < now)	{   TimedProc proc = first_task->proc;	    void *closure = first_task->closure;	    remove_onetime_task(proc, closure);	    (*proc)(closure);	}    }}//  calc_timeout calculates the timeout to pass to select().//  It returns://		NULL (if no timed tasks exist)//		zero time (if it's time for the next task)//		nonzero time (if it's not time yet)timeval *Scheduler::calc_timeout(){    static timeval sleep_interval;        if (ntasks)    {	timeval wake_time;	if (recurring_proc)	    wake_time = next_task_time;	if (!recurring_proc || first_task && first_task->when < wake_time)	    wake_time = first_task->when;	timeval now;	(void) gettimeofday(&now, NULL);	sleep_interval = wake_time - now;	if (sleep_interval.tv_sec < 0)	    timerclear(&sleep_interval);	return &sleep_interval;    }    else	return NULL;}////////////////////////////////////////////////////////////////////////////////  I/O handler code//  fd_to_info converts a file descriptor to a pointer into the//  fdinfo array.  On the way, it verifies that the array has//  been allocated far enough out.Scheduler::FDInfo *Scheduler::fd_to_info(int fd){    assert(fd >= 0);    if (nfds < fd + 1)    {	if (nfdinfo_alloc < fd + 1)	{	    unsigned newalloc = nfdinfo_alloc * 3 / 2 + 10;	    if (newalloc < fd + 1)		newalloc = fd + 1;	    FDInfo *newinfo = new FDInfo[newalloc];	    for (unsigned i = 0; i < nfds; i++)		newinfo[i] = fdinfo[i];	    delete [] fdinfo;	    fdinfo = newinfo;	    nfdinfo_alloc = newalloc;	}	// Zero all new fdinfo's.	memset(&fdinfo[nfds], 0, (fd + 1 - nfds) * sizeof *fdinfo);	nfds = fd + 1;    }    return &fdinfo[fd];}//  trim_fdinfo makes the fdinfo array smaller if its last entries//  aren't being used.  The memory isn't actually freed unless the//  array is completely zeroed out.voidScheduler::trim_fdinfo(){    for (FDInfo *fp = &fdinfo[nfds - 1]; nfds > 0; --nfds, --fp)	if (fp->read.handler || fp->write.handler)	    break;    if (!nfds)    {   delete [] fdinfo;	fdinfo = NULL;	nfdinfo_alloc = 0;    }}Scheduler::IOHandlerScheduler::install_io_handler(int fd, IOHandler handler, void *closure,			      IOTypeInfo *iotype){    assert(fd >= 0);    assert(handler);    FDInfo *fp = fd_to_info(fd);    IOHandler old_handler = (fp->*(iotype->iotype)).handler;    (fp->*(iotype->iotype)).handler = handler;    (fp->*(iotype->iotype)).closure = closure;    assert(!old_handler || FD_ISSET(fd, &iotype->fds));    if (!FD_ISSET(fd, &iotype->fds))    {        FD_SET(fd, &iotype->fds);        iotype->nbitsset++;    }    return old_handler;}Scheduler::IOHandlerScheduler::remove_io_handler(int fd, IOTypeInfo *iotype){    assert(fd >= 0 && fd < nfds);    FDInfo *fp = fd_to_info(fd);    IOHandler old_handler = (fp->*(iotype->iotype)).handler;    (fp->*(iotype->iotype)).handler = NULL;    (fp->*(iotype->iotype)).closure = NULL;    trim_fdinfo();    assert(old_handler);    if (FD_ISSET(fd, &iotype->fds))    {        FD_CLR(fd, &iotype->fds);        iotype->nbitsset--;    }    return old_handler;}Scheduler::IOHandlerScheduler::install_read_handler(int fd, IOHandler handler, void *closure){    return install_io_handler(fd, handler, closure, &read);}Scheduler::IOHandlerScheduler::remove_read_handler(int fd){    return remove_io_handler(fd, &read);}Scheduler::IOHandlerScheduler::install_write_handler(int fd, IOHandler handler, void *closure){    return install_io_handler(fd, handler, closure, &write);}Scheduler::IOHandlerScheduler::remove_write_handler(int fd){    return remove_io_handler(fd, &write);}voidScheduler::handle_io(const fd_set *fds, FDInfo::FDIOHandler FDInfo::* iotype){    if (fds)	for (int fd = 0; fd < nfds; fd++)	    if (FD_ISSET(fd, fds))	    {   FDInfo *fp = &fdinfo[fd];		assert(iotype == &FDInfo::read || iotype == &FDInfo::write);		(fp->*iotype).handler(fd, (fp->*iotype).closure);		// Remember, handler may move fdinfo array.	    }}// Scheduling priorities defined here: writable descriptors have// highest priority, followed by exceptionable descriptors, then// readable descriptors, then timed tasks have the lowest priority.voidScheduler::select(){    fd_set readfds, writefds;    readfds = Scheduler::read.fds;    writefds =  Scheduler::write.fds;    timeval *timeout   = calc_timeout();    int status = ::select(nfds, &readfds, &writefds, 0, timeout);    if (status == -1 && errno != EINTR)    {   Log::perror("select");		// Oh, no!	::exit(1);    }    if (status > 0)    {	// I/O is ready -- find it and do it.	handle_io( &writefds, &FDInfo::write );	handle_io(  &readfds, &FDInfo::read  );    }    // Check for tasks now.    do_tasks();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -