-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathBlueResManBackgroundCall.cpp
More file actions
141 lines (111 loc) · 2.83 KB
/
Copy pathBlueResManBackgroundCall.cpp
File metadata and controls
141 lines (111 loc) · 2.83 KB
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
// Copyright © 2014 CCP ehf.
#include "StdAfx.h"
#include "IBlueOS.h"
#include "BlueResManBackgroundCall.h"
#include "BlueResFile.h"
#include "IBlueResMan.h"
#include "IBluePython.h"
#include "BlueStatistics.h"
#include <Scheduler.h>
static CcpLogChannel_t s_ch = CCP_LOG_DEFINE_CHANNEL( "ResMan" );
BlueResManBackgroundCall::BlueResManBackgroundCall( IBlueResManBackgroundCall* theCall, uint32_t flags /*= 0 */ ) :
m_id( 0 ),
m_mainQueueId( 0 ),
m_flags( flags ),
m_isCanceling( 0 ),
m_backgroundCall( theCall )
{
#if CCP_STACKLESS
m_channel = SchedulerAPI()->PyChannel_New( NULL );
#endif
}
BlueResManBackgroundCall::~BlueResManBackgroundCall()
{
#if CCP_STACKLESS
Py_XDECREF( m_channel );
m_channel = nullptr;
#endif
}
void BlueResManBackgroundCall::AddToQueue()
{
BeResMan->AddToQueue(
BRMQ_BACKGROUND,
BlueResManBackgroundCall::DoTheCall,
this,
m_flags,
&m_id );
}
bool BlueResManBackgroundCall::Wait()
{
CCP_STATS_ZONE( __FUNCTION__ );
#if CCP_STACKLESS
if( !PyOS->CanYield() )
{
CCP_LOGERR_CH( s_ch, "Tasklet can't yield!" );
return true;
}
PyObject *ret = SchedulerAPI()->PyChannel_Receive( m_channel );
// We don't want to run in the context of the resman update. MarkAsDone below
// sends on the channel, switching execution to this tasklet. We'd rather want
// the update to finish as soon as possible.
PyOS->Yield();
if( !ret )
{
m_isCanceling = 1;
BeResMan->CancelFromQueue( BRMQ_BACKGROUND, m_id );
if( m_mainQueueId )
{
BeResMan->CancelFromQueue( BRMQ_MAIN, m_mainQueueId );
}
// Tasklet was killed
Py_DECREF( m_channel );
m_channel = nullptr;
return false;
}
Py_DECREF( ret );
return true;
#else
CCP_ASSERT_M( false, "Wait shouldn't be called without Stackless" );
return false;
#endif
}
void BlueResManBackgroundCall::DoTheCall( void* pContext )
{
CCP_STATS_ZONE( __FUNCTION__ );
BlueResManBackgroundCall* args = static_cast<BlueResManBackgroundCall*>( pContext );
if( args->m_backgroundCall )
{
args->m_backgroundCall->Perform();
}
if( !args->m_isCanceling )
{
BeResMan->AddToQueue( BRMQ_MAIN, MarkAsDone, pContext, args->m_flags, &args->m_mainQueueId );
}
}
void BlueResManBackgroundCall::MarkAsDone( void* pContext )
{
CCP_STATS_ZONE( __FUNCTION__ );
#if CCP_STACKLESS
BlueResManBackgroundCall* args = static_cast<BlueResManBackgroundCall*>( pContext );
SchedulerAPI()->PyChannel_Send( args->m_channel, Py_None );
#endif
}
bool BlueResManBackgroundCall::Issue( IBlueResManBackgroundCall* theCall, uint32_t flags /*= 0 */ )
{
#if CCP_STACKLESS
if( !PyOS->CanYield() )
{
theCall->Perform();
return true;
}
BlueResManBackgroundCall* cbArgs = CCP_NEW( "GetFileContents/cbArgs" )
BlueResManBackgroundCall( theCall, flags );
cbArgs->AddToQueue();
bool result = cbArgs->Wait();
CCP_DELETE cbArgs;
return result;
#else
theCall->Perform();
return true;
#endif
}