|
Packit Service |
a2489d |
/*
|
|
Packit Service |
a2489d |
* lftp - file transfer program
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net)
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
a2489d |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
a2489d |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
a2489d |
* (at your option) any later version.
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
a2489d |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
a2489d |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
a2489d |
* GNU General Public License for more details.
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
a2489d |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
a2489d |
*/
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#ifndef SMTASK_H
|
|
Packit Service |
a2489d |
#define SMTASK_H
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#include "PollVec.h"
|
|
Packit Service |
a2489d |
#include "TimeDate.h"
|
|
Packit Service |
a2489d |
#include "Ref.h"
|
|
Packit Service |
a2489d |
#include "xarray.h"
|
|
Packit Service |
a2489d |
#include "xlist.h"
|
|
Packit Service |
a2489d |
#include "misc.h"
|
|
Packit Service |
a2489d |
#include "Error.h"
|
|
Packit Service |
a2489d |
#include <errno.h>
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
class SMTask
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
virtual int Do() = 0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// all tasks list
|
|
Packit Service |
a2489d |
static xlist_head<SMTask> all_tasks;
|
|
Packit Service |
a2489d |
xlist<SMTask> all_tasks_node;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// ready (not suspended) tasks list
|
|
Packit Service |
a2489d |
static xlist_head<SMTask> ready_tasks;
|
|
Packit Service |
a2489d |
xlist<SMTask> ready_tasks_node;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// just created or resumed tasks
|
|
Packit Service |
a2489d |
static xlist_head<SMTask> new_tasks;
|
|
Packit Service |
a2489d |
xlist<SMTask> new_tasks_node;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// deleted and going to be destroyed tasks
|
|
Packit Service |
a2489d |
static xlist_head<SMTask> deleted_tasks;
|
|
Packit Service |
a2489d |
xlist<SMTask> deleted_tasks_node;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static PollVec block;
|
|
Packit Service |
a2489d |
enum { SMTASK_MAX_DEPTH=64 };
|
|
Packit Service |
a2489d |
static SMTask *stack[SMTASK_MAX_DEPTH];
|
|
Packit Service |
a2489d |
static int stack_ptr;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool suspended;
|
|
Packit Service |
a2489d |
bool suspended_slave;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int running;
|
|
Packit Service |
a2489d |
int ref_count;
|
|
Packit Service |
a2489d |
bool deleting;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int ScheduleThis();
|
|
Packit Service |
a2489d |
static int ScheduleNew();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
protected:
|
|
Packit Service |
a2489d |
enum
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
STALL=0,
|
|
Packit Service |
a2489d |
MOVED=1, // STALL|MOVED==MOVED.
|
|
Packit Service |
a2489d |
WANTDIE=2 // for AcceptSig
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// SuspendInternal and ResumeInternal usually suspend and resume slave tasks
|
|
Packit Service |
a2489d |
virtual void SuspendInternal() {}
|
|
Packit Service |
a2489d |
virtual void ResumeInternal();
|
|
Packit Service |
a2489d |
virtual void PrepareToDie() {} // it is called from Delete no matter of running and ref_count
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool Deleted() const { return deleting; }
|
|
Packit Service |
a2489d |
virtual ~SMTask();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
public:
|
|
Packit Service |
a2489d |
static void Block(int fd,int mask) { block.AddFD(fd,mask); }
|
|
Packit Service |
a2489d |
static void TimeoutU(int us) { block.AddTimeoutU(us); }
|
|
Packit Service |
a2489d |
static void Timeout(int ms) { TimeoutU(1000*ms); }
|
|
Packit Service |
a2489d |
static void TimeoutS(int s) { TimeoutU(1000000*s); }
|
|
Packit Service |
a2489d |
static bool Ready(int fd,int mask) { return block.FDReady(fd,mask); }
|
|
Packit Service |
a2489d |
static void SetNotReady(int fd,int mask) { block.FDSetNotReady(fd,mask); }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static TimeDate now;
|
|
Packit Service |
a2489d |
static void UpdateNow() { now.SetToCurrentTime(); }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static void Schedule();
|
|
Packit Service |
a2489d |
static int CollectGarbage();
|
|
Packit Service |
a2489d |
static void Block();
|
|
Packit Service |
a2489d |
static time_t last_block;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void Suspend();
|
|
Packit Service |
a2489d |
void Resume();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// SuspendSlave and ResumeSlave are used in SuspendInternal/ResumeInternal
|
|
Packit Service |
a2489d |
// to suspend/resume slave tasks
|
|
Packit Service |
a2489d |
void SuspendSlave();
|
|
Packit Service |
a2489d |
void ResumeSlave();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool IsSuspended() { return suspended|suspended_slave; }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
virtual const char *GetLogContext() { return 0; }
|
|
Packit Service |
a2489d |
static const char *GetCurrentLogContext() { return current->GetLogContext(); }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
SMTask();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void DeleteLater();
|
|
Packit Service |
a2489d |
static void Delete(SMTask *);
|
|
Packit Service |
a2489d |
void IncRefCount() { ref_count++; }
|
|
Packit Service |
a2489d |
void DecRefCount() { if(ref_count>0) ref_count--; }
|
|
Packit Service |
a2489d |
static SMTask *_MakeRef(SMTask *task) { if(task) task->IncRefCount(); return task; }
|
|
Packit Service |
a2489d |
static void _DeleteRef(SMTask *task) { if(task) { task->DecRefCount(); Delete(task); } }
|
|
Packit Service |
a2489d |
static SMTask *_SetRef(SMTask *task,SMTask *new_task);
|
|
Packit Service |
a2489d |
template<typename T> static T *MakeRef(T *task) { _MakeRef(task); return task; }
|
|
Packit Service |
a2489d |
static int Roll(SMTask *);
|
|
Packit Service |
a2489d |
int Roll() { return Roll(this); }
|
|
Packit Service |
a2489d |
static void RollAll(const TimeInterval &max_time);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static SMTask *current;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static void Enter(SMTask *task);
|
|
Packit Service |
a2489d |
static void Leave(SMTask *task);
|
|
Packit Service |
a2489d |
void Enter() { Enter(this); }
|
|
Packit Service |
a2489d |
void Leave() { Leave(this); }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static int TaskCount();
|
|
Packit Service |
a2489d |
static void PrintTasks();
|
|
Packit Service |
a2489d |
static bool NonFatalError(int err);
|
|
Packit Service |
a2489d |
static bool TemporaryNetworkError(int err) { return temporary_network_error(err); }
|
|
Packit Service |
a2489d |
static Error *SysError(int e=errno) { return new Error(e,strerror(e),!NonFatalError(e)); }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static void Cleanup();
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
class SMTaskInit : public SMTask
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int Do();
|
|
Packit Service |
a2489d |
public:
|
|
Packit Service |
a2489d |
SMTaskInit();
|
|
Packit Service |
a2489d |
~SMTaskInit();
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
template<class T> class SMTaskRef
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SMTaskRef<T>(const SMTaskRef<T>&); // disable cloning
|
|
Packit Service |
a2489d |
void operator=(const SMTaskRef<T>&); // and assignment
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
protected:
|
|
Packit Service |
a2489d |
T *ptr;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
public:
|
|
Packit Service |
a2489d |
SMTaskRef() { ptr=0; }
|
|
Packit Service |
a2489d |
SMTaskRef<T>(T *p) : ptr(SMTask::MakeRef(p)) {}
|
|
Packit Service |
a2489d |
~SMTaskRef<T>() { SMTask::_DeleteRef(ptr); ptr=0; }
|
|
Packit Service |
a2489d |
void operator=(T *p) { ptr=static_cast<T*>(SMTask::_SetRef(ptr,p)); }
|
|
Packit Service |
a2489d |
operator const T*() const { return ptr; }
|
|
Packit Service |
a2489d |
T *operator->() const { return ptr; }
|
|
Packit Service |
a2489d |
T *borrow() { if(ptr) ptr->DecRefCount(); return replace_value(ptr,(T*)0); }
|
|
Packit Service |
a2489d |
const T *get() const { return ptr; }
|
|
Packit Service |
a2489d |
T *get_non_const() const { return ptr; }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
template<class C> const SMTaskRef<C>& Cast() const
|
|
Packit Service |
a2489d |
{ void(static_cast<C*>(ptr)); return *(const SMTaskRef<C>*)this; }
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static const SMTaskRef<T> null;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void _set(T *p) { ptr=p; }
|
|
Packit Service |
a2489d |
void _clear() { ptr=0; }
|
|
Packit Service |
a2489d |
void unset() { *this=0; }
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
template<typename T>
|
|
Packit Service |
a2489d |
class TaskRefArray : public _RefArray< T,SMTaskRef<T> > {
|
|
Packit Service |
a2489d |
TaskRefArray& operator=(const TaskRefArray&); // make assignment fail
|
|
Packit Service |
a2489d |
TaskRefArray(const TaskRefArray&); // disable cloning
|
|
Packit Service |
a2489d |
public:
|
|
Packit Service |
a2489d |
TaskRefArray() : _RefArray< T,SMTaskRef<T> >() {}
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#endif /* SMTASK_H */
|