File: CobEngine.h

package info (click to toggle)
spring 105.0.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 108,860 kB
  • sloc: cpp: 467,785; ansic: 302,607; python: 12,925; java: 12,201; awk: 5,889; sh: 2,371; xml: 655; perl: 405; php: 276; objc: 194; makefile: 75; sed: 2
file content (153 lines) | stat: -rw-r--r-- 3,750 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef COB_ENGINE_H
#define COB_ENGINE_H

/*
 * Simple VM responsible for "scheduling" and running COB threads.
 * It also manages reading and caching of the actual .cob files.
 */

#include <vector>

#include "CobThread.h"
#include "System/creg/creg_cond.h"
#include "System/creg/STL_Queue.h"
#include "System/creg/STL_Map.h"


class CCobThread;
class CCobInstance;
class CCobFile;
class CCobFileHandler;

class CCobEngine
{
	CR_DECLARE_STRUCT(CCobEngine)

private:
	struct SleepingThread {
		CR_DECLARE_STRUCT(SleepingThread)

		int id;
		int wt;
	};

	struct CCobThreadComp: public std::binary_function<const SleepingThread&, const SleepingThread&, bool> {
	public:
		bool operator() (const SleepingThread& a, const SleepingThread& b) const {
			return (a.wt > b.wt);
		}
	};

public:
	void Init() {
		threadInstances.reserve(2048);
		tickAddedThreads.reserve(128);

		runningThreadIDs.reserve(512);
		waitingThreadIDs.reserve(512);

		threadCounter = 0;
	}
	void Kill() {
		// threadInstances is never explicitly iterated, so
		// calling clear_unordered_map (between reloads) is
		// unnecessary here
		threadInstances.clear();
		tickAddedThreads.clear();

		runningThreadIDs.clear();
		waitingThreadIDs.clear();

		while (!sleepingThreadIDs.empty()) {
			sleepingThreadIDs.pop();
		}
	}

	void Tick(int deltaTime);
	void ShowScriptError(const std::string& msg);


	CCobThread* GetThread(int threadID) {
		const auto it = threadInstances.find(threadID);

		if (it == threadInstances.end())
			return nullptr;

		return &(it->second);
	}

	bool RemoveThread(int threadID) {
		const auto it = threadInstances.find(threadID);

		if (it != threadInstances.end()) {
			threadInstances.erase(it);
			return true;
		}

		return false;
	}

	int AddThread(CCobThread&& thread);
	int GenThreadID() { return (threadCounter++); }
	int GetCurrentTime() const { return currentTime; }

	void QueueAddThread(CCobThread&& thread) { tickAddedThreads.emplace_back(std::move(thread)); }
	void AddQueuedThreads() {
		// move new threads spawned by START into threadInstances;
		// their ID's will already have been scheduled into either
		// waitingThreadIDs or sleepingThreadIDs
		for (CCobThread& t: tickAddedThreads) {
			AddThread(std::move(t));
		}

		tickAddedThreads.clear();
	}

	void ScheduleThread(const CCobThread* thread);
	void SanityCheckThreads(const CCobInstance* owner);

private:
	void TickThread(CCobThread* thread);

	void WakeSleepingThreads();
	void TickRunningThreads() {
		// advance all currently running threads
		for (const int threadID: runningThreadIDs) {
			TickThread(GetThread(threadID));
		}

		// a thread can never go from running->running, so clear the list
		// note: if preemption was to be added, this would no longer hold
		// however, TA scripts can not run preemptively anyway since there
		// aren't any synchronization methods available
		runningThreadIDs.clear();

		// prepare threads that will run next frame
		std::swap(runningThreadIDs, waitingThreadIDs);
	}

private:
	// registry of every thread across all script instances
	spring::unordered_map<int, CCobThread> threadInstances;
	// threads that are spawned during Tick
	std::vector<CCobThread> tickAddedThreads;

	std::vector<int> runningThreadIDs;
	std::vector<int> waitingThreadIDs;

	// stores <id, waketime> pairs s.t. after waking up the ID can be checked
	// for validity; thread owner might get removed while a thread is sleeping
	std::priority_queue<SleepingThread, std::vector<SleepingThread>, CCobThreadComp> sleepingThreadIDs;

	CCobThread* curThread = nullptr;

	int currentTime = 0;
	int threadCounter = 0;
};


extern CCobEngine* cobEngine;

#endif // COB_ENGINE_H