-
Notifications
You must be signed in to change notification settings - Fork 0
/
gBManager.cs
596 lines (507 loc) · 19.4 KB
/
gBManager.cs
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
#undef gB_DEBUG
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace gameBITS
{
/**
* Classe de gerenciamento dos recursos. Centraliza todas as referências de dados gerados a partir da estrutura do framework.
*/
public class gBManager
{
/**
* Construtor da classe.
*/
public gBManager()
{
#if (gB_DEBUG)
UnityEngine.Debug.Log("<color=green>gameBITS Framework: Gerenciador inicializado!</color>");
#endif
}
/**
* Destrutor da classe.
*/
~gBManager()
{
#if (gB_DEBUG)
UnityEngine.Debug.Log("<color=green>gameBITS Framework: Gerenciador finalizado!</color>");
#endif
}
/**
* Método de integração com ciclo de atualização da engine, também responsável por atualizar os artefatos concretos.
* @param Tempo entre o último frame e o atual, fornecido pela engine.
*/
public void Update(float delta_time)
{
gBManager manager = gBManager.Instance;
//Atualiza threads--------------------------------------------------------------------------------------------
uint threads_running = 0;
//Trava acesso à lista
lock (gBManager.requests_lock)
{
//Verifica status, atualiza objeto de requisição e remove da lista em caso de operação concluída
for (int request = manager.requests.Count - 1; request >= 0; request--)
{
gBRequest request_object = manager.requests[request];
//UnityEngine.Debug.Log("<color=green>" + "thread.IsAlive = " + request_object.thread.IsAlive + "</color>");
//UnityEngine.Debug.Log("thread.ThreadState = " + request_object.thread.ThreadState);
//Verifica se está rodando
if (request_object.thread.IsAlive && (request_object.thread.ThreadState & ThreadState.Running) == ThreadState.Running)
{
//UnityEngine.Debug.Log("<color=blue>" + "ESTÁ RODANDO" + "</color>");
request_object.is_running = true;
request_object.is_done = false;
threads_running++;
}
//Verifica se finalizou
else if ((request_object.thread.ThreadState & ThreadState.Stopped) == ThreadState.Stopped || (request_object.thread.ThreadState & ThreadState.Aborted) == ThreadState.Aborted)
{
//UnityEngine.Debug.Log("<color=blue>" + "FINALIZOU" + "</color>");
request_object.is_running = false;
request_object.is_done = true;
request_object.thread.Join();
//Remove da lista de requisições
manager.requests.RemoveAt(request);
}
}
//UnityEngine.Debug.Log("<color=green>" + "manager.max_threads = " + manager.max_threads + "</color>");
//UnityEngine.Debug.Log("<color=green>" + "threads_running = " + threads_running + "</color>");
//UnityEngine.Debug.Log("<color=green>" + "manager.requests.Count = " + manager.requests.Count + "</color>");
//Verifica se novas threads podem ser inicializadas
foreach (gBRequest request in manager.requests)
{
if (threads_running < manager.max_threads)
{
//UnityEngine.Debug.Log("<color=blue>" + "PODE RODAR MAIS THREADS" + "</color>");
if ((request.thread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
{
//UnityEngine.Debug.Log("<color=blue>" + "THREAD NÂO INICIALIZADA" + "</color>");
try
{
//UnityEngine.Debug.Log("<color=blue>" + "START()" + request.GetID() + "</color>");
request.thread.Start();
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e);
}
threads_running++;
}
}
else
{
break;
}
}
}
//------------------------------------------------------------------------------------------------------------
//Atualiza delta_time
manager.delta_time = delta_time;
//Atualiza artefatos à partir do nodo raiz registrado
if(manager.root_node != null)
{
//Cria lista de nodos a serem ignorados
HashSet<Guid> ignore = new HashSet<Guid>();
//Cria lista de nodos temporária
List<gBConcrete> nodes = manager.GenerateNodeUpdateList(ref ignore);
//Reconfigura flag de controle de alteração de hierarquia de nodos
manager.node_hierarchy_changed = false;
//Enquanto não atualizar todos os nodos
while(nodes.Count > 0)
{
//Inicia processo de atualização de nodos
nodes.Reverse();
int nodes_count = nodes.Count;
for (int current_node = nodes_count - 1; current_node >= 0; current_node--)
{
gBConcrete node = nodes[current_node];
//Adiciona nodo à lista de nodos a serem ignorados no caso de uma nova geração da lista de nodos
ignore.Add(node.GetID());
//Atualiza sistema de LOD do artefato, caso o artefato possua algum sistema de LOD atrelado
gBLODSystem lod_system = node.GetLODSystem();
if (lod_system != null)
{
lod_system.Update();
}
//Atualiza artefato
node.Update();
//Verifica flag de controle de alteração de hierarquia de nodos, se fora alterada, refaz a lista de nodos a serem atualizados
if(manager.node_hierarchy_changed == true)
{
//Gera lista de nodos novamente
nodes = manager.GenerateNodeUpdateList(ref ignore);
//Limpa flag
manager.node_hierarchy_changed = false;
//Sai do laço para recomeçar
break;
}
//Se não houve alteração, remove nodo da lista
else
{
nodes.RemoveAt(current_node);
}
}
}
}
}
/**
* Método de sinalização de alteração de hierarquia de nodos.
*/
public void NodeHierarchyChanged()
{
gBManager.Instance.node_hierarchy_changed = true;
}
/**
* Método de uso interno para geração de lista de nodos a serem atualizados.
* @param ignore_ids Lista de ids a serem ignorados na geração da lista.
* @return Retorna uma lista de nodos a serem atualizados.
*/
private List<gBConcrete> GenerateNodeUpdateList(ref HashSet<Guid> ignore)
{
//Copia lista para manipulação
HashSet<Guid> temp_ignore = new HashSet<Guid>();
foreach(Guid id in ignore)
{
temp_ignore.Add(id);
}
//Cria nova lista de nodos a serem atualizados
List<gBConcrete> nodes = new List<gBConcrete>();
if(gBManager.Instance.root_node != null)
{
gBManager.Instance.FindNodesToUpdate(gBManager.Instance.root_node, ref nodes, ref temp_ignore);
}
return nodes;
}
/**
* Método recursivo de busca e adição de nodos à lista fornecida.
* @param nodes_list Lista de nodos.
* @param ignore_ids ID's de nodos a serem ignorados.
*/
private void FindNodesToUpdate(gBConcrete node, ref List<gBConcrete> nodes, ref HashSet<Guid> ignore)
{
//Vasculha os nodos filhos de artefato
List<gBConcrete> child_nodes = node.GetChildNodes();
foreach (gBConcrete child_node in child_nodes)
{
gBManager.Instance.FindNodesToUpdate(child_node, ref nodes, ref ignore);
}
//Busca nodo na lista de ids a serem ignorados
foreach(Guid ignore_id in ignore)
{
if(ignore_id == node.GetID())
{
ignore.Remove(ignore_id);
return;
}
}
//Se não for ignorado, adiciona na lista
nodes.Add(node);
}
/**
* Define um artefato concreto como nodo raiz.
* @param Artefato a ser definido como nodo raiz.
*/
public void SetRootNode(gBConcrete node)
{
//Adiciona nodo na lista de nodos raiz
gBManager.Instance.root_node = node;
if (node != null)
{
node.SetParentNode(null);
}
}
/**
* Pega nodo raiz.
* @return Retorna artefato nodo.
*/
public gBConcrete GetRootNode()
{
return gBManager.Instance.root_node;
}
/**
* Método de inicialização das configurações do gerenciador.
*/
private void Setup()
{
gBManager manager = gBManager.Instance;
//Inicializa atributos
manager.delta_time = 0;
manager.max_threads = 2;
//Inicializa nodo raiz
manager.root_node = null;
//Inicializa mapa de armazenamento de ferramentas
manager.tools = new Dictionary<String, gBTool>();
//Inicializa lista de requisições assíncronas
manager.requests = new List<gBRequest>();
}
/**
* Método de atribuição de novo ID único.
* @param Recipiente a receber o novo ID.
*/
public void NewID(ref Guid id)
{
lock(gBManager.ids_lock)
{
id = Guid.NewGuid();
}
}
/**
* Método de registro de ferramenta pelo uso de "apelido" único.
* @param tool Referência da ferrramenta.
* @param alias Apelido a ser usado.
*/
public bool AddTool(String alias, gBTool tool)
{
gBManager manager = gBManager.Instance;
bool temp_return;
lock(gBManager.tools_lock)
{
if (manager.tools.ContainsKey(alias))
{
temp_return = false;
}
else
{
manager.tools.Add(alias, tool);
temp_return = true;
}
}
return temp_return;
}
/**
* Método de remoção de registro de ferramenta pelo "apelido" único.
* @param alias Apelido da ferramenta.
* @return Retorna status da operação.
*/
public bool RemoveTool(String alias)
{
gBManager manager = gBManager.Instance;
bool temp_return;
lock (gBManager.tools_lock)
{
temp_return = manager.tools.Remove(alias);
}
return temp_return;
}
/**
* Método de remoção de registro de ferramentas.
*/
public void RemoveAllTools()
{
gBManager manager = gBManager.Instance;
lock (gBManager.tools_lock)
{
manager.tools.Clear();
}
}
/**
* Método de seleção de ferramenta pelo "apelido" único.
* @param alias Apelido da ferramenta.
*/
public gBTool SelectTool(String alias)
{
gBManager manager = gBManager.Instance;
gBTool temp_return = null;
lock (gBManager.tools_lock)
{
if (manager.tools.ContainsKey(alias))
{
temp_return = manager.tools[alias];
}
}
return temp_return;
}
/**
* Método de aquisição de instância única.
* @return Retorna instância única de si.
*/
public static gBManager Instance
{
get
{
if (gBManager.instance == null)
{
gBManager.instance = new gBManager();
//Realiza a chamada do método de configurações iniciais do gerenciador
gBManager.instance.Setup();
}
return gBManager.instance;
}
}
/**
* Método de destruição de instância única.
*/
public bool Destroy()
{
if (gBManager.instance == null)
{
return false;
}
else
{
gBManager.instance.Terminate();
gBManager.instance = null;
return true;
}
}
/**
* Método de aquisição de delta time.
* @return Retorna valor de último delta time registrado.
*/
public float GetDeltaTime()
{
return gBManager.Instance.delta_time;
}
/**
* Método chamado na finalização da engine.
*/
private void Terminate()
{
//Limpar threads
//Trava acesso à lista
lock (gBManager.requests_lock)
{
foreach(gBRequest request in this.requests)
{
request.thread.Abort();
}
}
//Limpa nodos
this.SetRootNode(null);
//Limpa tools
this.RemoveAllTools();
}
/**
* Método chamado para configurar o número máximo de threads simultâneas.
* @param Número máximo de threads a correr simultâneamente.
*/
public void SetMaxThreads(uint max_threads)
{
gBManager manager = gBManager.Instance;
manager.max_threads = max_threads;
}
/**
* Método de aquisição do número máximo de threads simultâneas.
* @return Número máximo de threads.
*/
public uint GetMaxThreads()
{
gBManager manager = gBManager.Instance;
return manager.max_threads;
}
/**
* Método chamado para registrar uma nova requisição. Uma thread é gerada e registrada na requisição. A requisição é inserida na lista conforme prioridade.
* @param Objeto de requisição.
*/
public void RegisterRequest(gBRequest request)
{
gBManager manager = gBManager.Instance;
//Trava acesso à lista
lock (gBManager.requests_lock)
{
if (manager.requests.Count > 0)
{
//Busca posição correta na lista de threads conforme prioridade
for (int position = 0; position < manager.requests.Count; position++)
{
//Se prioridade da requisição consultada for menor, encaixa na frente dela
if (manager.requests[position].priority < request.priority)
{
//Registra requisição e thread
manager.requests.Insert(position, request);
break;
}
//Se for última e não encontrou outra requisição de menos prioridade, adiciona ao fim da lista
else if (position == manager.requests.Count - 1)
{
//Registra requisição e thread
manager.requests.Add(request);
break;
}
}
}
else
{
//Registra requisição e thread
manager.requests.Add(request);
}
}
}
/**
* Método de aquisição do número atual de threads em andamento.
* @return Número atual de threads rodando.
*/
public uint GetCurrentRunningThreads()
{
gBManager manager = gBManager.Instance;
uint threads_running = 0;
//Trava acesso à lista
lock(gBManager.requests_lock)
{
foreach (gBRequest request in manager.requests)
{
//Verifica se está rodando
if (request.is_running)
{
threads_running++;
}
}
}
return threads_running;
}
/**
* Método de aquisição do número total de threads na fila.
* @return Número atual de threads na fila.
*/
public uint GetCurrentThreads()
{
gBManager manager = gBManager.Instance;
uint threads = 0;
//Trava acesso à lista
lock (gBManager.requests_lock)
{
threads = (uint)manager.requests.Count;
}
return threads;
}
//******************************************************************
// Atributos da classe *********************************************
//******************************************************************
/**
* Registro de ferramentas pelo uso de apelidos.
*/
private Dictionary<String, gBTool> tools;
/**
* Artefato que representa nodo raiz.
*/
private gBConcrete root_node;
/**
* Referência para instância única.
*/
private static gBManager instance;
/**
* Tempo entre o último frame e o atual, informado pela engine no processo de atualização.
*/
private float delta_time;
/**
* Número máximo de threads executadas simultaneamente.
*/
private uint max_threads;
/**
* Threads em curso.
*/
private List<gBRequest> requests;
/**
* Flag que sinaliza se estrutura de nodos foi alterada.
*/
private bool node_hierarchy_changed = false;
/**
* Para controle de threads.
*/
private static object requests_lock = new Object();
private static object tools_lock = new Object();
private static object ids_lock = new Object();
}
}