mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
P3D_check_request(timeout)
This commit is contained in:
parent
35bf03caf1
commit
a4fcdbe5b9
@ -44,12 +44,21 @@ class panda3d(package):
|
||||
# automatically be included as well, and we end up with a pretty
|
||||
# complete list that way.
|
||||
module('direct.directbase.DirectStart',
|
||||
'direct.actor.*',
|
||||
'direct.controls.*',
|
||||
'direct.directdevices.*',
|
||||
'direct.directnotify.*',
|
||||
'direct.directtools.*',
|
||||
'direct.directutil.*',
|
||||
'direct.distributed.*',
|
||||
'direct.fsm.*',
|
||||
'direct.gui.*',
|
||||
'direct.interval.*',
|
||||
'direct.particles.*',
|
||||
'direct.showbase.*',
|
||||
'direct.actor.Actor',
|
||||
'direct.fsm.FSM',
|
||||
'direct.interval.IntervalGlobal',
|
||||
'direct.particles.ParticleEffect',
|
||||
'direct.directutil.Mopath')
|
||||
'direct.showutil.*',
|
||||
'direct.stdpy.*')
|
||||
|
||||
|
||||
# Exclude these GUI toolkits; they're big, and many applications don't
|
||||
# use them. We define them as separate, optional packages, below.
|
||||
|
@ -404,7 +404,8 @@ check_request() {
|
||||
// Function: P3DInstanceManager::wait_request
|
||||
// Access: Public
|
||||
// Description: Does not return until a request is pending on some
|
||||
// instance, or until no instances remain. Use
|
||||
// instance, or until no instances remain, or until the
|
||||
// indicated time in seconds has elapsed. Use
|
||||
// check_request to retrieve the pending request. Due
|
||||
// to the possibility of race conditions, it is possible
|
||||
// for this function to return when there is in fact no
|
||||
@ -412,9 +413,60 @@ check_request() {
|
||||
// the request first).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void P3DInstanceManager::
|
||||
wait_request() {
|
||||
wait_request(double timeout) {
|
||||
#ifdef _WIN32
|
||||
int stop_tick = int(GetTickCount() + timeout * 1000.0);
|
||||
#else
|
||||
struct timeval stop_time;
|
||||
gettimeofday(&stop_time, NULL);
|
||||
|
||||
int seconds = (int)floor(timeout);
|
||||
stop_time.tv_sec += seconds;
|
||||
stop_time.tv_usec += (int)((timeout - seconds) * 1000.0);
|
||||
if (stop_time.tv_usec > 1000) {
|
||||
stop_time.tv_usec -= 1000;
|
||||
++stop_time.tv_sec;
|
||||
}
|
||||
#endif
|
||||
|
||||
_request_ready.acquire();
|
||||
if (check_request() != (P3DInstance *)NULL) {
|
||||
_request_ready.release();
|
||||
return;
|
||||
}
|
||||
if (_instances.empty()) {
|
||||
_request_ready.release();
|
||||
return;
|
||||
}
|
||||
|
||||
// No pending requests; go to sleep.
|
||||
_request_ready.wait(timeout);
|
||||
|
||||
while (true) {
|
||||
#ifdef _WIN32
|
||||
int remaining_ticks = stop_tick - GetTickCount();
|
||||
if (remaining_ticks <= 0) {
|
||||
break;
|
||||
}
|
||||
timeout = remaining_ticks * 0.001;
|
||||
#else
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
struct timeval remaining;
|
||||
remaining.tv_sec = stop_time.tv_sec - now.tv_sec;
|
||||
remaining.tv_usec = stop_time.tv_usec - now.tv_usec;
|
||||
|
||||
if (remaining.tv_usec < 0) {
|
||||
remaining.tv_usec += 1000;
|
||||
--remaining.tv_sec;
|
||||
}
|
||||
if (remaining.tv_sec < 0) {
|
||||
break;
|
||||
}
|
||||
timeout = remaining.tv_sec + remaining.tv_usec * 0.001;
|
||||
#endif
|
||||
|
||||
if (check_request() != (P3DInstance *)NULL) {
|
||||
_request_ready.release();
|
||||
return;
|
||||
@ -425,7 +477,7 @@ wait_request() {
|
||||
}
|
||||
|
||||
// No pending requests; go to sleep.
|
||||
_request_ready.wait();
|
||||
_request_ready.wait(timeout);
|
||||
}
|
||||
_request_ready.release();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
P3DInstance *validate_instance(P3D_instance *instance);
|
||||
|
||||
P3DInstance *check_request();
|
||||
void wait_request();
|
||||
void wait_request(double timeout);
|
||||
|
||||
P3DHost *get_host(const string &host_url);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "p3dStringObject.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
// Use a simple lock to protect the C-style API functions in this
|
||||
// module from parallel access by multiple threads in the host.
|
||||
@ -405,21 +406,65 @@ P3D_instance_get_request(P3D_instance *instance) {
|
||||
}
|
||||
|
||||
P3D_instance *
|
||||
P3D_check_request(bool wait) {
|
||||
P3D_check_request(double timeout) {
|
||||
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||
P3D_instance *inst = inst_mgr->check_request();
|
||||
|
||||
if (inst != NULL || !wait) {
|
||||
if (inst != NULL || timeout <= 0.0) {
|
||||
RELEASE_LOCK(_api_lock);
|
||||
return inst;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int stop_tick = int(GetTickCount() + timeout * 1000.0);
|
||||
#else
|
||||
struct timeval stop_time;
|
||||
gettimeofday(&stop_time, NULL);
|
||||
|
||||
int seconds = (int)floor(timeout);
|
||||
stop_time.tv_sec += seconds;
|
||||
stop_time.tv_usec += (int)((timeout - seconds) * 1000.0);
|
||||
if (stop_time.tv_usec > 1000) {
|
||||
stop_time.tv_usec -= 1000;
|
||||
++stop_time.tv_sec;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now we have to block until a request is available.
|
||||
RELEASE_LOCK(_api_lock);
|
||||
inst_mgr->wait_request(timeout);
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
inst = inst_mgr->check_request();
|
||||
|
||||
while (inst == NULL && inst_mgr->get_num_instances() != 0) {
|
||||
#ifdef _WIN32
|
||||
int remaining_ticks = stop_tick - GetTickCount();
|
||||
if (remaining_ticks <= 0) {
|
||||
break;
|
||||
}
|
||||
timeout = remaining_ticks * 0.001;
|
||||
#else
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
struct timeval remaining;
|
||||
remaining.tv_sec = stop_time.tv_sec - now.tv_sec;
|
||||
remaining.tv_usec = stop_time.tv_usec - now.tv_usec;
|
||||
|
||||
if (remaining.tv_usec < 0) {
|
||||
remaining.tv_usec += 1000;
|
||||
--remaining.tv_sec;
|
||||
}
|
||||
if (remaining.tv_sec < 0) {
|
||||
break;
|
||||
}
|
||||
timeout = remaining.tv_sec + remaining.tv_usec * 0.001;
|
||||
#endif
|
||||
|
||||
RELEASE_LOCK(_api_lock);
|
||||
inst_mgr->wait_request();
|
||||
inst_mgr->wait_request(timeout);
|
||||
ACQUIRE_LOCK(_api_lock);
|
||||
inst = inst_mgr->check_request();
|
||||
}
|
||||
|
@ -738,10 +738,9 @@ P3D_instance_get_request_func(P3D_instance *instance);
|
||||
If any open instance has a pending request, this function will
|
||||
return a pointer to one of them (which you may then pass to
|
||||
P3D_instance_get_request_func). If no instances have a pending
|
||||
request, this function will return NULL. If wait is true, this
|
||||
function will never return NULL unless there are no instances open;
|
||||
instead, it will wait indefinitely until there is a request
|
||||
available.
|
||||
request, this function will return NULL. This function will not
|
||||
return until at least timeout seconds have elapsed, or a request is
|
||||
available, whichever comes first.
|
||||
|
||||
Note that, due to race conditions, it is possible for this function
|
||||
to return a P3D_instance that does not in fact have any requests
|
||||
@ -749,7 +748,7 @@ P3D_instance_get_request_func(P3D_instance *instance);
|
||||
should always verify that the return value of
|
||||
P3D_instance_get_request() is not NULL. */
|
||||
typedef P3D_instance *
|
||||
P3D_check_request_func(bool wait);
|
||||
P3D_check_request_func(double timeout);
|
||||
|
||||
/* A request retrieved by P3D_instance_get_request() should eventually
|
||||
be passed here, after it has been handled, to deallocate its
|
||||
|
@ -36,6 +36,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
// The amount of time in seconds to wait for new messages.
|
||||
static const double wait_cycle = 0.2;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::Constructor
|
||||
// Access: Public
|
||||
@ -61,7 +64,7 @@ run(int argc, char *argv[]) {
|
||||
// We prefix a "+" sign to tell gnu getopt not to parse options
|
||||
// following the first not-option parameter. (These will be passed
|
||||
// into the sub-process.)
|
||||
const char *optstr = "+mu:p:ft:s:o:l:h";
|
||||
const char *optstr = "+mu:p:fw:t:s:o:l:h";
|
||||
|
||||
bool allow_multiple = false;
|
||||
string download_url = PANDA_PACKAGE_HOST_URL;
|
||||
@ -92,7 +95,7 @@ run(int argc, char *argv[]) {
|
||||
verify_contents = true;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'w':
|
||||
if (strcmp(optarg, "toplevel") == 0) {
|
||||
window_type = P3D_WT_toplevel;
|
||||
} else if (strcmp(optarg, "embedded") == 0) {
|
||||
@ -102,7 +105,14 @@ run(int argc, char *argv[]) {
|
||||
} else if (strcmp(optarg, "hidden") == 0) {
|
||||
window_type = P3D_WT_hidden;
|
||||
} else {
|
||||
cerr << "Invalid value for -t: " << optarg << "\n";
|
||||
cerr << "Invalid value for -w: " << optarg << "\n";
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (!parse_token(optarg)) {
|
||||
cerr << "Web tokens (-t) must be of the form token=value: " << optarg << "\n";
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
@ -248,13 +258,13 @@ run(int argc, char *argv[]) {
|
||||
DispatchMessage(&msg);
|
||||
|
||||
// Check for new requests from the Panda3D plugin.
|
||||
P3D_instance *inst = P3D_check_request(false);
|
||||
P3D_instance *inst = P3D_check_request(wait_cycle);
|
||||
while (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
if (request != (P3D_request *)NULL) {
|
||||
handle_request(request);
|
||||
}
|
||||
inst = P3D_check_request(false);
|
||||
inst = P3D_check_request(wait_cycle);
|
||||
}
|
||||
|
||||
while (!_url_getters.empty() &&
|
||||
@ -276,7 +286,7 @@ run(int argc, char *argv[]) {
|
||||
// Not an embedded window, so we don't have our own window to
|
||||
// generate Windows events. Instead, just wait for requests.
|
||||
while (!_instances.empty()) {
|
||||
P3D_instance *inst = P3D_check_request(false);
|
||||
P3D_instance *inst = P3D_check_request(wait_cycle);
|
||||
if (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
if (request != (P3D_request *)NULL) {
|
||||
@ -294,7 +304,7 @@ run(int argc, char *argv[]) {
|
||||
EventLoopRef main_loop = GetMainEventLoop();
|
||||
EventLoopTimerUPP timer_upp = NewEventLoopTimerUPP(st_timer_callback);
|
||||
EventLoopTimerRef timer;
|
||||
EventTimerInterval interval = 200 * kEventDurationMillisecond;
|
||||
EventTimerInterval interval = wait_cycle * kEventDurationSecond;
|
||||
InstallEventLoopTimer(main_loop, interval, interval,
|
||||
timer_upp, this, &timer);
|
||||
RunApplicationEventLoop();
|
||||
@ -310,7 +320,7 @@ run(int argc, char *argv[]) {
|
||||
|
||||
// Now wait while we process pending requests.
|
||||
while (!_instances.empty()) {
|
||||
P3D_instance *inst = P3D_check_request(false);
|
||||
P3D_instance *inst = P3D_check_request(wait_cycle);
|
||||
if (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
if (request != (P3D_request *)NULL) {
|
||||
@ -647,7 +657,7 @@ create_instance(const string &p3d, P3D_window_type window_type,
|
||||
}
|
||||
|
||||
// Build up the token list.
|
||||
pvector<P3D_token> tokens;
|
||||
Tokens tokens = _tokens;
|
||||
P3D_token token;
|
||||
|
||||
string log_basename;
|
||||
@ -745,7 +755,11 @@ usage() {
|
||||
<< " time, but additional arguments may not be passed to any of the\n"
|
||||
<< " applictions.\n\n"
|
||||
|
||||
<< " -t [toplevel|embedded|fullscreen|hidden]\n"
|
||||
<< " -t token=value\n"
|
||||
<< " Defines a web token or parameter to pass to the application(s).\n"
|
||||
<< " This simulates a <param> entry in an <object> tag.\n\n"
|
||||
|
||||
<< " -w [toplevel|embedded|fullscreen|hidden]\n"
|
||||
<< " Specify the type of graphic window to create. If you specify\n"
|
||||
<< " \"embedded\", a new window is created to be the parent.\n\n"
|
||||
|
||||
@ -775,6 +789,33 @@ usage() {
|
||||
<< DTOOL_PLATFORM << "\" .\n\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::parse_token
|
||||
// Access: Private
|
||||
// Description: Parses a web token of the form token=value, and
|
||||
// stores it in _tokens. Returns true on success, false
|
||||
// on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Panda3D::
|
||||
parse_token(char *arg) {
|
||||
char *equals = strchr(arg, '=');
|
||||
if (equals == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Directly munge the C string to truncate it at the equals sign.
|
||||
// Classic C tricks.
|
||||
*equals = '\0';
|
||||
P3D_token token;
|
||||
token._keyword = strdup(arg);
|
||||
token._value = strdup(equals + 1);
|
||||
*equals = '=';
|
||||
|
||||
_tokens.push_back(token);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Panda3D::parse_int_pair
|
||||
// Access: Private
|
||||
@ -857,13 +898,13 @@ st_timer_callback(EventLoopTimerRef timer, void *user_data) {
|
||||
void Panda3D::
|
||||
timer_callback(EventLoopTimerRef timer) {
|
||||
// Check for new requests from the Panda3D plugin.
|
||||
P3D_instance *inst = P3D_check_request(false);
|
||||
P3D_instance *inst = P3D_check_request(0.0);
|
||||
while (inst != (P3D_instance *)NULL) {
|
||||
P3D_request *request = P3D_instance_get_request(inst);
|
||||
if (request != (P3D_request *)NULL) {
|
||||
handle_request(request);
|
||||
}
|
||||
inst = P3D_check_request(false);
|
||||
inst = P3D_check_request(0.0);
|
||||
}
|
||||
|
||||
// Check the download tasks.
|
||||
|
@ -63,6 +63,7 @@ private:
|
||||
void delete_instance(P3D_instance *instance);
|
||||
|
||||
void usage();
|
||||
bool parse_token(char *arg);
|
||||
bool parse_int_pair(char *arg, int &x, int &y);
|
||||
|
||||
void report_downloading_package(P3D_instance *instance);
|
||||
@ -83,6 +84,9 @@ private:
|
||||
typedef pset<P3D_instance *> Instances;
|
||||
Instances _instances;
|
||||
|
||||
typedef pvector<P3D_token> Tokens;
|
||||
Tokens _tokens;
|
||||
|
||||
// This nested class keeps track of active URL requests.
|
||||
class URLGetter {
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user