-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathImgLoader.h
96 lines (92 loc) · 2.75 KB
/
ImgLoader.h
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
#pragma once
#include "ImgItem.h"
#include "CountingSemaphore.h"
#include <Windows.h>
#include <list>
#include <functional>
#include <memory>
#include <string>
#include <vector>
class LoaderItem
{
public:
LoaderItem(ImgItem* imgitem, std::function<void()> handler)
: imgitem_(imgitem), loadcompleteevent_(handler) { }
~LoaderItem()
{
CloseLoaderItemThread();
}
LoaderItem(const LoaderItem&) = delete;
LoaderItem& operator=(const LoaderItem&) = delete;
ImgItem* imgitem() const { return imgitem_; }
HANDLE loaderitemthread() const { return loaderitemthread_; }
void set_loaderitemthread(HANDLE loaderitemthread) { loaderitemthread_ = loaderitemthread; }
void CloseLoaderItemThread()
{
if (loaderitemthread_ != INVALID_HANDLE_VALUE)
{
CloseHandle(loaderitemthread_);
loaderitemthread_ = INVALID_HANDLE_VALUE;
}
}
void LoadComplete()
{
if (loadcompleteevent_ != nullptr)
{
loadcompleteevent_();
}
}
private:
ImgItem* imgitem_{ nullptr };
HANDLE loaderitemthread_{ INVALID_HANDLE_VALUE };
std::function<void()> loadcompleteevent_{ nullptr };
};
class ImgLoader
{
public:
static constexpr auto kMaximumLoaderCount = 2; // TODO: adjust logic around this limit once GDI+ gets replaced completely
static constexpr auto kCleanupCycleCountTrigger = 29;
public:
ImgLoader()
{
if (!InitializeCriticalSectionAndSpinCount(&queuecriticalsection_, 0x00000400))
{
// TODO: handle error
}
cancelevent_ = CreateEvent(NULL, TRUE, FALSE, NULL);
workevent_ = CreateEvent(NULL, TRUE, FALSE, NULL);
loadersemaphore_.SetupSemaphore(kMaximumLoaderCount);
LoadAsync();
}
~ImgLoader()
{
StopLoading();
DeleteCriticalSection(&queuecriticalsection_);
CloseHandle(cancelevent_);
CloseHandle(workevent_);
if (loopthread_ != NULL)
{
CloseHandle(loopthread_);
}
}
ImgLoader(const ImgLoader&) = delete;
ImgLoader& operator=(const ImgLoader&) = delete;
void QueueItem(ImgItem* imgitem, BOOL loadnext = FALSE);
void StopLoading();
private:
std::list<ImgItem*> queue_;
std::list<std::unique_ptr<LoaderItem>> loaderitems_;
HANDLE workevent_;
HANDLE cancelevent_;
HANDLE loopthread_{ INVALID_HANDLE_VALUE };
BOOL cancellationflag_{};
CountingSemaphore loadersemaphore_;
CRITICAL_SECTION queuecriticalsection_;
private:
void LoadAsync();
DWORD Loop();
ImgItem* GetNextItem();
void CleanupItemThreadObjects();
static DWORD WINAPI StaticThreadLoop(void* imgloaderinstance);
static DWORD WINAPI StaticThreadLoad(void* imgiteminstance);
};