File: CobThread.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 (167 lines) | stat: -rw-r--r-- 4,430 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef COB_THREAD_H
#define COB_THREAD_H

#include <string>
#include <array>

#include "CobInstance.h"
#include "Lua/LuaRules.h"

class CCobFile;
class CCobInstance;


class CCobThread
{
	CR_DECLARE_STRUCT(CCobThread)
	CR_DECLARE_SUB(CallInfo)

public:
	// default and copy-ctor are creg only
	CCobThread() {}

	CCobThread(CCobInstance* _cobInst);
	CCobThread(CCobThread&& t) { *this = std::move(t); }
	CCobThread(const CCobThread& t) { *this = t; }

	~CCobThread() { Stop(); }

	CCobThread& operator = (CCobThread&& t);
	CCobThread& operator = (const CCobThread& t);

	enum State {Init, Sleep, Run, Dead, WaitTurn, WaitMove};

	/**
	 * Returns false if this thread is dead and needs to be killed.
	 */
	bool Tick();
	/**
	 * This function sets the thread in motion. Should only be called once.
	 * If schedule is false the thread is not added to the scheduler, and thus
	 * it is expected that the starter is responsible for ticking it.
	 */
	void Start(int functionId, int sigMask, const std::array<int, 1 + MAX_COB_ARGS>& args, bool schedule);
	void Stop();

	void SetID(int threadID) { id = threadID; }
	void SetState(State s) { state = s; }

	/**
	 * Sets a callback that will be called when the thread dies.
	 * There can be only one.
	 */
	void SetCallback(CCobInstance::ThreadCallbackType cb, int cbp) {
		cbType = cb;
		cbParam = cbp;
	}
	void MakeGarbage() {
		cobInst = nullptr;
		cobFile = nullptr;
	}


	/**
	 * @brief Checks whether the stack has at least size items.
	 * @returns min(size, stack.size())
	 */
	int CheckStack(unsigned int size, bool warn);
	void InitStack(unsigned int n, CCobThread* t);

	/**
	 * Shows an errormessage which includes the current state of the script
	 * interpreter.
	 */
	void ShowError(const char* msg);
	void AnimFinished(CUnitScript::AnimType type, int piece, int axis);

	const std::string& GetName();

	int GetID() const { return id; }
	int GetStackVal(int pos) const { return dataStack[pos]; }
	int GetWakeTime() const { return wakeTime; }
	int GetRetCode() const { return retCode; }
	int GetSignalMask() const { return signalMask; }
	State GetState() const { return state; }

	bool Reschedule(CUnitScript::AnimType type) const {
		return ((state == WaitMove && type == CCobInstance::AMove) || (state == WaitTurn && type == CCobInstance::ATurn));
	}

	bool IsDead() const { return (state == Dead); }
	bool IsGarbage() const { return (cobInst == nullptr); }
	bool IsWaiting() const { return (waitAxis != -1); }

	// script instance that owns this thread
	CCobInstance* cobInst = nullptr;
	CCobFile* cobFile = nullptr;

protected:
	struct CallInfo {
		CR_DECLARE_STRUCT(CallInfo)
		int functionId = -1;
		int returnAddr = -1;
		int stackTop = -1;
	};

	void LuaCall();

	bool PushCallStack(CallInfo v) { return (callStackSize < callStack.size() && PushCallStackRaw(v)); }
	bool PushDataStack(     int v) { return (dataStackSize < dataStack.size() && PushDataStackRaw(v)); }

	bool PushCallStackRaw(CallInfo v) { assert(callStackSize < callStack.size()); callStack[callStackSize++] = v; return true; }
	bool PushDataStackRaw(     int v) { assert(dataStackSize < dataStack.size()); dataStack[dataStackSize++] = v; return true; }

	CallInfo& PushCallStackRef() {
		if (callStackSize < callStack.size())
			return (PushCallStackRefRaw());
		return callStack[0];
	}
	CallInfo& PushCallStackRefRaw() {
		assert(callStackSize < callStack.size());
		return callStack[callStackSize++];
	}

	int LocalFunctionID() const { return callStack[callStackSize - (callStackSize > 0)].functionId; }
	int LocalReturnAddr() const { return callStack[callStackSize - (callStackSize > 0)].returnAddr; }
	int LocalStackFrame() const { return callStack[callStackSize - (callStackSize > 0)].stackTop  ; }

	int PopDataStack() {
		if (dataStackSize > 0)
			return dataStack[--dataStackSize];

		return 0;
	}

protected:
	int id = -1;
	int pc = 0;

	int wakeTime = 0;
	int paramCount = 0;
	int retCode = -1;
	int cbParam = 0;
	int signalMask = 0;

	int waitAxis = -1;
	int waitPiece = -1;

	int callStackSize = 0;
	int dataStackSize = 0;

	int errorCounter = 100;

	int luaArgs[MAX_LUA_COB_ARGS] = {0};


	std::array<CallInfo, 64> callStack;
	std::array<int, 1024> dataStack;
	// std::vector<int> execTrace;

	State state = Init;

	CCobInstance::ThreadCallbackType cbType = CCobInstance::CBNone;
};

#endif // COB_THREAD_H