mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 14:46:24 +00:00
Directory Structure [step 1]: moving files
working on #672 NOTE: This commit can't be compiled!!
This commit is contained in:
316
deps/acelite/ace/SUN_Proactor.cpp
vendored
Normal file
316
deps/acelite/ace/SUN_Proactor.cpp
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
#include "ace/SUN_Proactor.h"
|
||||
|
||||
#if defined (ACE_HAS_AIO_CALLS) && defined (sun)
|
||||
|
||||
#include "ace/Task_T.h"
|
||||
#include "ace/Log_Category.h"
|
||||
#include "ace/Object_Manager.h"
|
||||
|
||||
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
||||
|
||||
ACE_SUN_Proactor::ACE_SUN_Proactor (size_t max_aio_operations)
|
||||
: ACE_POSIX_AIOCB_Proactor (max_aio_operations,
|
||||
ACE_POSIX_Proactor::PROACTOR_SUN),
|
||||
condition_ (mutex_)
|
||||
{
|
||||
// To provide correct virtual calls.
|
||||
create_notify_manager ();
|
||||
|
||||
// we should start pseudo-asynchronous accept task
|
||||
// one per all future acceptors
|
||||
|
||||
this->get_asynch_pseudo_task ().start ();
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
ACE_SUN_Proactor::~ACE_SUN_Proactor (void)
|
||||
{
|
||||
this->close ();
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::handle_events (ACE_Time_Value &wait_time)
|
||||
{
|
||||
// Decrement <wait_time> with the amount of time spent in the method
|
||||
ACE_Countdown_Time countdown (&wait_time);
|
||||
return this->handle_events_i (&wait_time);
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::handle_events (void)
|
||||
{
|
||||
return this->handle_events_i (0);
|
||||
}
|
||||
|
||||
int ACE_SUN_Proactor::wait_for_start (ACE_Time_Value * abstime)
|
||||
{
|
||||
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
|
||||
|
||||
ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1));
|
||||
|
||||
if (this->num_started_aio_ != 0) // double check
|
||||
return 0;
|
||||
|
||||
return this->condition_.wait (abstime);
|
||||
|
||||
#else
|
||||
|
||||
return 0; // or -1 ???
|
||||
|
||||
#endif /* ACE_MT_SAFE */
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::handle_events_i (ACE_Time_Value *delta)
|
||||
{
|
||||
int retval = 0;
|
||||
aio_result_t *result = 0;
|
||||
|
||||
if (0 == delta)
|
||||
{
|
||||
if (this->num_started_aio_ == 0)
|
||||
this->wait_for_start (0);
|
||||
|
||||
result = aiowait (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->num_started_aio_ == 0)
|
||||
{
|
||||
// Decrement delta with the amount of time spent waiting
|
||||
ACE_Countdown_Time countdown (delta);
|
||||
ACE_Time_Value tv (*delta);
|
||||
tv += ACE_OS::gettimeofday ();
|
||||
if (this->wait_for_start (&tv) == -1)
|
||||
return -1;
|
||||
}
|
||||
struct timeval delta_tv = *delta;
|
||||
result = aiowait (&delta_tv);
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
// timeout, do nothing,
|
||||
// we should process "post_completed" queue
|
||||
}
|
||||
else if (reinterpret_cast<long> (result) == -1)
|
||||
{
|
||||
// Check errno for EINVAL,EAGAIN,EINTR ??
|
||||
switch (errno)
|
||||
{
|
||||
case EINTR : // aiowait() was interrupted by a signal.
|
||||
case EINVAL: // there are no outstanding asynchronous I/O requests.
|
||||
break; // we should process "post_completed" queue
|
||||
|
||||
default: // EFAULT
|
||||
ACELIB_ERROR_RETURN ((LM_ERROR,
|
||||
ACE_TEXT("%N:%l:(%P | %t)::%p \nNumAIO=%d\n"),
|
||||
ACE_TEXT("ACE_SUN_Proactor::handle_events: aiowait failed"),
|
||||
num_started_aio_),
|
||||
-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int error_status = 0;
|
||||
size_t transfer_count = 0;
|
||||
|
||||
ACE_POSIX_Asynch_Result *asynch_result =
|
||||
find_completed_aio (result,
|
||||
error_status,
|
||||
transfer_count);
|
||||
|
||||
if (asynch_result != 0)
|
||||
{
|
||||
// Call the application code.
|
||||
this->application_specific_code (asynch_result,
|
||||
transfer_count,
|
||||
0, // No completion key.
|
||||
error_status); // Error
|
||||
retval++;
|
||||
}
|
||||
}
|
||||
|
||||
// process post_completed results
|
||||
retval += this->process_result_queue ();
|
||||
|
||||
return retval > 0 ? 1 : 0 ;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::get_result_status (ACE_POSIX_Asynch_Result* asynch_result,
|
||||
int &error_status,
|
||||
size_t &transfer_count)
|
||||
{
|
||||
|
||||
// Get the error status of the aio_ operation.
|
||||
error_status = asynch_result->aio_resultp.aio_errno;
|
||||
ssize_t op_return = asynch_result->aio_resultp.aio_return;
|
||||
|
||||
// ****** from Sun man pages *********************
|
||||
// Upon completion of the operation both aio_return and aio_errno
|
||||
// are set to reflect the result of the operation.
|
||||
// AIO_INPROGRESS is not a value used by the system
|
||||
// so the client may detect a change in state
|
||||
// by initializing aio_return to this value.
|
||||
|
||||
if (error_status == EINPROGRESS || op_return == AIO_INPROGRESS)
|
||||
return 0; // not completed
|
||||
|
||||
if (op_return < 0)
|
||||
transfer_count = 0; // zero bytes transferred
|
||||
else
|
||||
transfer_count = static_cast<size_t> (op_return);
|
||||
|
||||
return 1; // completed
|
||||
}
|
||||
|
||||
ACE_POSIX_Asynch_Result *
|
||||
ACE_SUN_Proactor::find_completed_aio (aio_result_t *result,
|
||||
int &error_status,
|
||||
size_t &transfer_count)
|
||||
{
|
||||
ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, 0));
|
||||
|
||||
size_t ai;
|
||||
error_status = -1;
|
||||
transfer_count = 0;
|
||||
|
||||
// we call find_completed_aio always with result != 0
|
||||
|
||||
for (ai = 0; ai < aiocb_list_max_size_; ai++)
|
||||
if (aiocb_list_[ai] != 0 && //check for non zero
|
||||
result == &aiocb_list_[ai]->aio_resultp)
|
||||
break;
|
||||
|
||||
if (ai >= aiocb_list_max_size_) // not found
|
||||
return 0; // means somebody else uses aio directly!!!
|
||||
|
||||
ACE_POSIX_Asynch_Result *asynch_result = result_list_[ai];
|
||||
|
||||
if (this->get_result_status (asynch_result,
|
||||
error_status,
|
||||
transfer_count) == 0)
|
||||
{ // should never be
|
||||
ACELIB_ERROR ((LM_ERROR,
|
||||
ACE_TEXT("%N:%l:(%P | %t)::%p\n"),
|
||||
ACE_TEXT("ACE_SUN_Proactor::find_completed_aio:")
|
||||
ACE_TEXT("should never be !!!\n")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
aiocb_list_[ai] = 0;
|
||||
result_list_[ai] = 0;
|
||||
aiocb_list_cur_size_--;
|
||||
|
||||
num_started_aio_--;
|
||||
|
||||
start_deferred_aio ();
|
||||
//make attempt to start deferred AIO
|
||||
//It is safe as we are protected by mutex_
|
||||
|
||||
return asynch_result;
|
||||
}
|
||||
|
||||
// start_aio_i has new return codes
|
||||
// 0 successful start
|
||||
// 1 try later, OS queue overflow
|
||||
// -1 invalid request and other errors
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::start_aio_i (ACE_POSIX_Asynch_Result *result)
|
||||
{
|
||||
ACE_TRACE ("ACE_SUN_Proactor::start_aio_i");
|
||||
|
||||
int ret_val;
|
||||
const ACE_TCHAR *ptype;
|
||||
|
||||
// ****** from Sun man pages *********************
|
||||
// Upon completion of the operation both aio_return and aio_errno
|
||||
// are set to reflect the result of the operation.
|
||||
// AIO_INPROGRESS is not a value used by the system
|
||||
// so the client may detect a change in state
|
||||
// by initializing aio_return to this value.
|
||||
result->aio_resultp.aio_return = AIO_INPROGRESS;
|
||||
result->aio_resultp.aio_errno = EINPROGRESS;
|
||||
|
||||
// Start IO
|
||||
switch (result->aio_lio_opcode)
|
||||
{
|
||||
case LIO_READ :
|
||||
ptype = ACE_TEXT ("read");
|
||||
ret_val = aioread (result->aio_fildes,
|
||||
(char *) result->aio_buf,
|
||||
result->aio_nbytes,
|
||||
result->aio_offset,
|
||||
SEEK_SET,
|
||||
&result->aio_resultp);
|
||||
break;
|
||||
|
||||
case LIO_WRITE :
|
||||
ptype = ACE_TEXT ("write");
|
||||
ret_val = aiowrite (result->aio_fildes,
|
||||
(char *) result->aio_buf,
|
||||
result->aio_nbytes,
|
||||
result->aio_offset,
|
||||
SEEK_SET,
|
||||
&result->aio_resultp);
|
||||
break;
|
||||
|
||||
default:
|
||||
ptype = ACE_TEXT ("?????");
|
||||
ret_val = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret_val == 0)
|
||||
{
|
||||
this->num_started_aio_++;
|
||||
if (this->num_started_aio_ == 1) // wake up condition
|
||||
this->condition_.broadcast ();
|
||||
}
|
||||
else // if (ret_val == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == ENOMEM) // Defer - retry this later.
|
||||
ret_val = 1;
|
||||
else
|
||||
ACELIB_ERROR ((LM_ERROR,
|
||||
ACE_TEXT ("%N:%l:(%P | %t)::start_aio: aio%s %p\n"),
|
||||
ptype,
|
||||
ACE_TEXT ("queueing failed\n")));
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int
|
||||
ACE_SUN_Proactor::cancel_aiocb (ACE_POSIX_Asynch_Result *result)
|
||||
{
|
||||
ACE_TRACE ("ACE_SUN_Proactor::cancel_aiocb");
|
||||
int rc = ::aiocancel (&result->aio_resultp);
|
||||
if (rc == 0) // AIO_CANCELED
|
||||
{
|
||||
// after aiocancel Sun does not notify us
|
||||
// so we should send notification
|
||||
// to save POSIX behavoir.
|
||||
// Also we should do this for deffered aio's
|
||||
|
||||
result->set_error (ECANCELED);
|
||||
result->set_bytes_transferred (0);
|
||||
this->putq_result (result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
ACE_POSIX_Proactor::Proactor_Type
|
||||
ACE_SUN_Proactor::get_impl_type (void)
|
||||
{
|
||||
return PROACTOR_SUN;
|
||||
}
|
||||
|
||||
ACE_END_VERSIONED_NAMESPACE_DECL
|
||||
|
||||
#endif /* ACE_HAS_AIO_CALLS && sun */
|
||||
Reference in New Issue
Block a user