This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/WWOnline/WaitCondition.h

344 lines
8.5 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/WWOnline/WaitCondition.h $
*
* DESCRIPTION
* This class encapsulates a wait condition.
*
* To wait on an event, create a wait condition. Pass the condition, or a
* set of conditions, to WaitingCondition::Wait_For(). This will block
* until the conditions are met, the user cancels the wait, or the timeout
* is reached. This will also cause the wait popup to be displayed.
*
* PROGRAMMER
* Steven Clinard
* $Author: Denzil_l $
*
* VERSION INFO
* $Modtime: 1/18/02 3:08p $
* $Revision: 9 $
*
******************************************************************************/
#ifndef __WAITCONDITION_H__
#define __WAITCONDITION_H__
#include "RefCounted.h"
#include "RefPtr.h"
#include <WWLib\Notify.h>
#include <WWLib\CallbackHook.h>
#include <WWLib\WideString.h>
#if defined(_MSC_VER)
#pragma warning(push, 3)
#endif
#include <vector>
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
class CallbackHook;
class WaitCondition :
public RefCounted
{
public:
enum WaitResult {Waiting, ConditionMet, UserCancel, TimeOut, Error};
// Wait for this condition
virtual WaitResult WaitFor(CallbackHook& hook, unsigned long timeout = 30000);
/* Wait_Beginning is called when the wait actually begins.
* This useful if the activity being monitored should only begin after the
* wait has started.
*
* Normally, the request should begin as soon as possible and the condition
* may be met before the wait begins; this avoids the whole wait popup in
* the first place.
*
* Serially chained waits may require prerequisite conditions to be met
* before the request that initiates this wait. In this case, a derived
* wait class could override Wait_Beginning to make the request.
*/
virtual void WaitBeginning(void) = 0;
// Get the result of the wait in progress.
virtual WaitResult GetResult(void) = 0;
// End the wait.
virtual void EndWait(WaitResult, const wchar_t*) = 0;
// Get a text description of completed wait
virtual const wchar_t* GetResultText(void) const = 0;
// Get a text description of the wait in progress.
virtual const wchar_t* GetWaitText(void) const = 0;
// Get the timeout in milliseconds for this wait condition
virtual unsigned long GetTimeout(void) const = 0;
protected:
WaitCondition();
virtual ~WaitCondition();
WaitCondition(const WaitCondition&);
const WaitCondition& operator=(const WaitCondition&);
};
// Waits for a single event.
class SingleWait :
public WaitCondition
{
public:
static RefPtr<SingleWait> Create(const wchar_t* waitText, unsigned long timeout = 30000);
virtual void WaitBeginning(void);
virtual WaitResult GetResult(void);
virtual void EndWait(WaitResult, const wchar_t*);
virtual const wchar_t* GetResultText(void) const;
virtual const wchar_t* GetWaitText(void) const;
virtual void SetWaitText(const wchar_t* waitText);
virtual unsigned long GetTimeout(void) const;
protected:
SingleWait(const wchar_t* waitText, unsigned long timeout = 30000);
virtual ~SingleWait();
SingleWait(const SingleWait&);
const SingleWait& operator=(const SingleWait&);
WaitResult mEndResult;
WideStringClass mEndText;
WideStringClass mWaitText;
unsigned long mTimeout;
unsigned long mStartTime;
};
// Waits for multiple events.
// All events must be satisfied and must occur in the order in which they are added.
class SerialWait :
public WaitCondition
{
public:
static RefPtr<SerialWait> Create(void);
void Add(const RefPtr<WaitCondition>&);
int RemainingWaits(void) const;
virtual void WaitBeginning(void);
virtual WaitResult GetResult(void);
virtual void EndWait(WaitResult, const wchar_t*);
virtual const wchar_t* GetResultText(void) const;
virtual const wchar_t* GetWaitText(void) const;
virtual unsigned long GetTimeout(void) const;
protected:
SerialWait();
virtual ~SerialWait();
SerialWait(const SerialWait&);
const SerialWait& operator=(const SerialWait&);
std::vector< RefPtr<WaitCondition> > mWaits;
mutable int mCurrentWait;
mutable WaitResult mEndResult;
mutable WideStringClass mEndText;
unsigned long mMaxTimeout;
unsigned long mStartTime;
};
// Waits for multiple events.
// All events are started at the same time. All events must be satisfied,
// but may occur in any order.
class ANDWait :
public WaitCondition
{
public:
static RefPtr<ANDWait> Create(const wchar_t*);
void Add(const RefPtr<WaitCondition>&);
virtual void WaitBeginning(void);
virtual WaitResult GetResult(void);
virtual void EndWait(WaitResult, const wchar_t*);
virtual const wchar_t* GetResultText(void) const;
virtual const wchar_t* GetWaitText(void) const;
virtual unsigned long GetTimeout(void) const;
protected:
ANDWait(const wchar_t*);
virtual ~ANDWait();
ANDWait(const ANDWait&);
const ANDWait& operator=(const ANDWait&);
std::vector< RefPtr<WaitCondition> > mWaits;
mutable WaitResult mEndResult;
mutable WideStringClass mEndText;
WideStringClass mWaitText;
unsigned long mMaxTimeout;
unsigned long mStartTime;
};
// ORWait: Waits for multiple events.
// All events are started at the same time. Wait ends when any event is satisfied.
class ORWait :
public WaitCondition
{
public:
static RefPtr<ORWait> Create(const wchar_t*);
void Add(const RefPtr<WaitCondition>&);
virtual void WaitBeginning(void);
virtual WaitResult GetResult(void);
virtual void EndWait(WaitResult, const wchar_t*);
virtual const wchar_t* GetResultText(void) const;
virtual const wchar_t* GetWaitText(void) const;
virtual unsigned long GetTimeout(void) const
{return mMaxTimeout;}
protected:
ORWait(const wchar_t*);
virtual ~ORWait();
ORWait(const ORWait&);
const ORWait& operator=(const ORWait&);
std::vector< RefPtr<WaitCondition> > mWaits;
mutable WaitResult mEndResult;
mutable WideStringClass mEndText;
WideStringClass mWaitText;
unsigned long mMaxTimeout;
unsigned long mStartTime;
};
// Wait for an event from a notifier
template<typename Event> class EventWait :
public SingleWait,
public Observer<Event>
{
public:
static RefPtr< EventWait<Event> > Create(const wchar_t* waitText)
{new EventWait(waitText);}
static RefPtr< EventWait<Event> > CreateAndObserve(Notifier<Event>& notifier,
const wchar_t* waitText)
{
EventWait<Event>* wait = new EventWait(waitText);
notifier.AddObserver(*wait);
return wait;
}
virtual void HandleNotification(Event&)
{if (mEndResult == Waiting) {EndWait(ConditionMet);}}
protected:
EventWait(const wchar_t* waitText) :
SingleWait(waitText)
{}
EventWait(const EventWait<Event>&);
const EventWait<Event>& operator=(const EventWait<Event>&);
};
// Wait for an event with a particular value from a notifier
template<typename Event> class EventValueWait :
public SingleWait,
public Observer<Event>
{
public:
static RefPtr< EventValueWait<Event> > Create(const Event& value, const wchar_t* waitText)
{new EventValueWait(value, waitText);}
static RefPtr< EventValueWait<Event> > CreateAndObserve(Notifier<Event>& notifier,
const Event value, const wchar_t* waitText)
{
EventValueWait<Event>* wait = new EventValueWait(value, waitText);
notifier.AddObserver(*wait);
return wait;
}
virtual void HandleNotification(Event& event)
{
if (mEndResult == Waiting)
{
if (event == mMatchValue)
{
EndWait(ConditionMet, L"");
}
else
{
EndWait(mEndResult, L"");
}
}
}
protected:
EventValueWait(const Event& value, const wchar_t* waitText) :
SingleWait(waitText),
mMatchValue(value)
{}
EventValueWait(const EventValueWait<Event>&);
const EventValueWait& operator=(const EventValueWait&);
Event mMatchValue;
};
#endif // __WAITCONDITION_H__