Job
- JobSerializer에 등록할 함수를 캡슐화한 클래스이다.
- 실행할 함수와 매개변수를 관리한다.
📄 Job.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Server.Game
{
public interface IJob
{
void Execute();
}
public class Job : IJob
{
Action _action;
public Job(Action action)
{
_action = action;
}
public void Execute()
{
_action.Invoke();
}
}
public class Job<T1> : IJob
{
Action<T1> _action;
T1 _t1;
public Job(Action<T1> action, T1 t1)
{
_action = action;
_t1 = t1;
}
public void Execute()
{
_action.Invoke(_t1);
}
}
public class Job<T1, T2> : IJob
{
Action<T1, T2> _action;
T1 _t1;
T2 _t2;
public Job(Action<T1, T2> action, T1 t1, T2 t2)
{
_action = action;
_t1 = t1;
_t2 = t2;
}
public void Execute()
{
_action.Invoke(_t1, _t2);
}
}
public class Job<T1, T2, T3> : IJob
{
Action<T1, T2, T3> _action;
T1 _t1;
T2 _t2;
T3 _t3;
public Job(Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3)
{
_action = action;
_t1 = t1;
_t2 = t2;
_t3 = t3;
}
public void Execute()
{
_action.Invoke(_t1, _t2, _t3);
}
}
}
JobTimer
JobTimerElem
- JobTimer에 등록할 Job을 캡슐화한 구조체이다.
- Job과 실행 시간을 관리한다.
📄 JobTimer.cs
using System;
using System.Collections.Generic;
using System.Text;
using ServerCore;
namespace Server.Game
{
struct JobTimerElem : IComparable<JobTimerElem>
{
public int execTick;
public IJob job;
public int CompareTo(JobTimerElem other)
{
return other.execTick - execTick;
}
}
JobTimer
- 예약된 Job을 JobTimerElem로 변환하여 관리한다.
- 예약 실행 시간이 된 Job을 전부 실행한다.
📄 JobTimer.cs
public class JobTimer
{
PriorityQueue<JobTimerElem> _pq = new PriorityQueue<JobTimerElem>();
object _lock = new object();
public void Push(IJob job, int tickAfter = 0)
{
JobTimerElem jobElement;
jobElement.execTick = System.Environment.TickCount + tickAfter;
jobElement.job = job;
lock (_lock)
{
_pq.Push(jobElement);
}
}
public void Flush()
{
while (true)
{
int now = System.Environment.TickCount;
JobTimerElem jobElement;
lock (_lock)
{
if (_pq.Count == 0)
break;
jobElement = _pq.Peek();
if (jobElement.execTick > now)
break;
_pq.Pop();
}
jobElement.job.Execute();
}
}
}
}
JobSerializer
- 등록된 Job을 Queue로, 예약된 Job을 JobTimer로 모두 관리한다.
- 일정 시간마다 등록된 Job과 예약된 Job을 전부 순차적으로 실행한다.
📄 JobSerializer.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Server.Game
{
public class JobSerializer
{
JobTimer _timer = new JobTimer();
Queue<IJob> _jobQueue = new Queue<IJob>();
object _lock = new object();
bool _flush = false;
public void PushAfter(int tickAfter, Action action) { PushAfter(tickAfter, new Job(action)); }
public void PushAfter<T1>(int tickAfter, Action<T1> action, T1 t1) { PushAfter(tickAfter, new Job<T1>(action, t1)); }
public void PushAfter<T1, T2>(int tickAfter, Action<T1, T2> action, T1 t1, T2 t2) { PushAfter(tickAfter, new Job<T1, T2>(action, t1, t2)); }
public void PushAfter<T1, T2, T3>(int tickAfter, Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3) { PushAfter(tickAfter, new Job<T1, T2, T3>(action, t1, t2, t3)); }
public void PushAfter(int tickAfter, IJob job)
{
_timer.Push(job, tickAfter);
}
public void Push(Action action) { Push(new Job(action)); }
public void Push<T1>(Action<T1> action, T1 t1) { Push(new Job<T1>(action, t1)); }
public void Push<T1, T2>(Action<T1, T2> action, T1 t1, T2 t2) { Push(new Job<T1, T2>(action, t1, t2)); }
public void Push<T1, T2, T3>(Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3) { Push(new Job<T1, T2, T3>(action, t1, t2, t3)); }
public void Push(IJob job)
{
lock (_lock)
{
_jobQueue.Enqueue(job);
}
}
public void Flush()
{
_timer.Flush();
while (true)
{
IJob job = Pop();
if (job == null)
return;
job.Execute();
}
}
IJob Pop()
{
lock (_lock)
{
if (_jobQueue.Count == 0)
{
_flush = false;
return null;
}
return _jobQueue.Dequeue();
}
}
}
}
빌드 및 실행
