summaryrefslogtreecommitdiff
path: root/src/nw4r/ut/ut_DvdLockedFileStream.cpp
blob: a4753d5c87247ed0e35c6050f5d8ebcc55d6535f (plain)
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
// Ported From https://github.com/kiwi515/ogws/blob/master/src/nw4r/ut/ut_DvdLockedFileStream.cpp

#include "nw4r/ut.h" // IWYU pragma: export
#include "rvl/OS.h"  // IWYU pragma: export

namespace nw4r {
namespace ut {

NW4R_UT_RTTI_DEF_DERIVED(DvdLockedFileStream, DvdFileStream);

OSThreadQueue DvdLockedFileStream::sThreadQueue;
OSMutex DvdLockedFileStream::sMutex;
bool DvdLockedFileStream::sInitialized = false;

void DvdLockedFileStream::InitMutex_() {
    BOOL enabled = OSDisableInterrupts();

    if (!sInitialized) {
        OSInitMutex(&sMutex);
        OSInitThreadQueue(&sThreadQueue);
        sInitialized = true;
    }

    OSRestoreInterrupts(enabled);
}

DvdLockedFileStream::DvdLockedFileStream(s32 entrynum) : DvdFileStream(entrynum) {
    mCancelFlag = false;
    InitMutex_();
}

DvdLockedFileStream::DvdLockedFileStream(const DVDFileInfo *info, bool close) : DvdFileStream(info, close) {
    mCancelFlag = false;
    InitMutex_();
}

DvdLockedFileStream::~DvdLockedFileStream() {}

void DvdLockedFileStream::Close() {
    DvdFileStream::Close();
    mCancelFlag = false;
}

s32 DvdLockedFileStream::Read(void *dst, u32 size) {
    if (!LockMutex()) {
        return DVD_RESULT_CANCELED;
    }
    s32 ret = DvdFileStream::Read(dst, size);
    UnlockMutex();
    return ret;
}

s32 DvdLockedFileStream::Peek(void *dst, u32 size) {
    if (!LockMutex()) {
        return DVD_RESULT_CANCELED;
    }
    s32 ret = DvdFileStream::Peek(dst, size);
    UnlockMutex();
    return ret;
}

void DvdLockedFileStream::Cancel() {
    CancelMutex();
    DvdFileStream::Cancel();
}

bool DvdLockedFileStream::LockMutex() {
    BOOL enabled = OSDisableInterrupts();
    while (!OSTryLockMutex(&sMutex)) {
        OSSleepThread(&sThreadQueue);
        if (mCancelFlag) {
            OSRestoreInterrupts(enabled);
            return false;
        }
    };
    OSRestoreInterrupts(enabled);
    return true;
}

void DvdLockedFileStream::UnlockMutex() {
    BOOL enabled = OSDisableInterrupts();
    OSUnlockMutex(&sMutex);
    OSWakeupThread(&sThreadQueue);
    OSRestoreInterrupts(enabled);
}

void DvdLockedFileStream::CancelMutex() {
    BOOL enabled = OSDisableInterrupts();
    mCancelFlag = true;
    OSWakeupThread(&sThreadQueue);
    OSRestoreInterrupts(enabled);
}

} // namespace ut
} // namespace nw4r