ROOT logo
// $Id: Eventor.cxx 2614 2011-12-14 03:33:09Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

//________________________________________________________________________
// Eventor
//
// Base-class for glasses that wish to acquire their own threads.
//
//________________________________________________________________________

#include "Eventor.h"
#include <Glasses/SaturnInfo.h>
#include "Eventor.c7"

#include <Ephra/Mountain.h>
#include <Glasses/ZKing.h>
#include <Glasses/ZQueen.h>
#include <Gled/GledMirDefs.h>
#include <Gled/GledOperatorDefs.h>


#include <signal.h>
#include <errno.h>

ClassImp(Eventor);

/**************************************************************************/

void Eventor::_init()
{
  mTotalTime = mRunTime = 0;
  mBeatsToDo = -1; mBeatsDone = 0; mLocBeatsDone = 0;
  mStampInterval = 100; mInterBeatMS = 0;

  mHost = 0;

  bMultix     = false; bSignalSafe = false;
  bContinuous = true;  bUseDynCast = true;
  bTrapILL = bTrapBUS = bTrapFPE = bTrapSEGV = false;

  bRunning = bSuspended = bPerforming = bXMultix = false;

  mEventID      = 0;
  mInternalTime = 0;
  mEpochType    = ET_DanceStart;
  mTimeSource   = TS_System;
  mTimeStep     = 1;
  mTimeEpoch    = 0;
}

/**************************************************************************/

Mountain* Eventor::GetChaItOss()
{
  return mSaturn->GetChaItOss();
}

/**************************************************************************/

void Eventor::AdEndarkenment()
{
  // !!!! if thread running clomp it
}

void Eventor::AdUnfoldment()
{
  Operator::AdUnfoldment();
  mLocBeatsDone = mBeatsDone;

  // !!!! multix can change ... would better lock that!!!
  // anyway dislike the duplication in op_arg.
  // Too lazy to write the manual Set Methods?

  if(bXMultix && bRunning) {
    if(mHost == 0) {
      mHost = GetQueen()->GetKing()->GetSaturnInfo();
    }
    if(!bSuspended) {
      mSaturn->GetChaItOss()->Start(this);
    } else {
      mSaturn->GetChaItOss()->Start(this, true);
    }
  }
}

/**************************************************************************/
// Dance & Beat methods
/**************************************************************************/

Operator::Arg* Eventor::PreDance(Operator::Arg* op_arg)
{
  // Eventor::PreDance() is called as the first thing from
  // Mountain::OperatorBeat().
  //
  // It is supposed to instantiate and set Operator::Arg* op_arg to
  // meaningfull values and return it.
  //
  // If you sub-class the Operator::Arg, make sure to also perform the
  // house-keeping tasks performed here or call this method with
  // non-zero op_arg.
  //
  // Return value of 0 signifies error and results in immediate
  // termination of the thread. No other methods are called.

  if(op_arg == 0) op_arg = new Operator::Arg;

  op_arg->fEventor      = this;
  op_arg->fMultix	= bMultix;
  op_arg->fSignalSafe	= bSignalSafe;
  op_arg->fContinuous	= bContinuous;
  op_arg->fUseDynCast	= bUseDynCast;

  return op_arg;
}

void Eventor::PostDance(Operator::Arg* op_arg)
{
  // Eventor::PostDance() is called from Mountain::OperatorBeat() when
  // Eventor throws Operator::OE_Done to request termination of the
  // thread.
  //
  // If Operator::OE_Stop or Operator::OE_Break is thrown, this method
  // is *not* called, but either OnStop() or OnBreak().
}

/**************************************************************************/

void Eventor::PreBeat(Operator::Arg* op_arg) throw(Operator::Exception)
{
  // Eventor::PreBeat() is called from Mountain::OperatorBeat() prior
  // to calling Operate.

  switch(mTimeSource)
  {
    case TS_System:
      mInternalTime = op_arg->fBeatStart.ToDouble() - mTimeEpoch;
      break;
    case TS_IntStep:
      mInternalTime += mTimeStep;
      break;
  }

  mTimeStack.clear();
  mTimeStack.push_back(mInternalTime);
}

void Eventor::PostBeat(Operator::Arg* op_arg) throw(Operator::Exception)
{
  // Eventor::PostBeat() is called from Mountain::OperatorBeat() after
  // Operate (unless an exception was thrown from Operate's traversal).

  ++mLocBeatsDone;
  bool done = (mBeatsToDo != -1 && mLocBeatsDone >= mBeatsToDo);
  if(mStampInterval == 0 || mLocBeatsDone % mStampInterval == 0 || done) {
    OP_EXE_OR_SP_MIR(this, SetBeatsDone, mLocBeatsDone);
  }
  if(done) {
    throw( Operator::Exception(this, Operator::OE_Done, "reached required beat count") );
  }
}

/**************************************************************************/
// Handlers for Start/Suspend/Exit
/**************************************************************************/

void Eventor::OnStart(Operator::Arg* op_arg)
{
  OP_EXE_OR_SP_MIR(this, SetRunning, true);
  OP_EXE_OR_SP_MIR(this, SetXMultix, op_arg->fMultix);

  // Set epoch on start; for multix moons use the streamed value.
  // ???? Does gettimeofday return the UTC time?
  // If not, must offset the epoch by correct amount on moons.
  if ((op_arg->fMultix && IsSunOrFireSpace()) || !op_arg->fMultix)
  {
    switch(mEpochType)
    {
      case ET_Manual:
        mInternalTime = mTimeEpoch;
        break;
      case ET_DanceStart:
        mTimeEpoch = op_arg->fStart.ToDouble();
        if (!op_arg->fMultix)
          OP_EXE_OR_SP_MIR(this, SetTimeEpoch, mTimeEpoch);
        break;
    }
  }

  SetPerforming(true);
}

void Eventor::OnSuspend(Operator::Arg* op_arg)
{
  OP_EXE_OR_SP_MIR(this, SetSuspended, true);
}

void Eventor::OnResume(Operator::Arg* op_arg)
{
  OP_EXE_OR_SP_MIR(this, SetSuspended, false);
}

void Eventor::OnExit(Operator::Arg* op_arg)
{
  if (bSuspended) {
    OP_EXE_OR_SP_MIR(this, SetSuspended, false);
  }
  OP_EXE_OR_SP_MIR(this, SetRunning, false);
  OP_EXE_OR_SP_MIR(this, SetTotalTime, (op_arg->fStop - op_arg->fStart).ToDouble());
  OP_EXE_OR_SP_MIR(this, SetRunTime, op_arg->fBeatSum.ToDouble());
  SetPerforming(false);
}

/**************************************************************************/
// Handlers for different exceptions
/**************************************************************************/

void Eventor::OnContinue(Operator::Arg* op_arg, Operator::Exception& op_exc)
{
  // Called from Mountain::DancerBeat() upon catching "continue" exception.
}

void Eventor::OnWait(Operator::Arg* op_arg, Operator::Exception& op_exc)
{
  // Called from Mountain::DancerBeat() upon catching "wait" exception.
}

void Eventor::OnStop(Operator::Arg* op_arg, Operator::Exception& op_exc)
{
  // Called from Mountain::DancerBeat() upon catching "stop" exception.
}

void Eventor::OnBreak(Operator::Arg* op_arg, Operator::Exception& op_exc)
{
  // Called from Mountain::DancerBeat() upon catching "break" exception.
}

void Eventor::OnBreak(Operator::Arg* op_arg, const TString& msg)
{
  // Called from Mountain::DancerBeat() upon catching an un-native
  // exception.
}

void Eventor::OnTerminalSignal(Operator::Arg* op_arg, GThread::Signal sid)
{
  // Called from Mountain::DancerBeat() upon receiving a terminal
  // signal. FPE, BUS, SEGV, ILL

}

/**************************************************************************/
// User interface for thread control
/**************************************************************************/

void Eventor::Start()
{
  static const Exc_t _eh("Eventor::Start ");

  if(mHost == 0) {
    SetHost(GetQueen()->GetKing()->GetSaturnInfo());
  }

  if(!bMultix && mHost != mSaturn->GetSaturnInfo()) return;

  if(bRunning) {
    ISwarn(_eh + "already running.");
    return;
  }
  if(bSuspended) {
    ISwarn(_eh + "paused; use Resume to continue.");
    return;
  }
  mSaturn->GetChaItOss()->Start(this);
}

void Eventor::Stop()
{
  static const Exc_t _eh("Eventor::Stop ");

  if(!bXMultix && mHost != mSaturn->GetSaturnInfo()) return;

  if(!bRunning) {
    ISwarn(_eh + "not running.");
    return;
  }

  mSaturn->GetChaItOss()->Stop(this);
}

void Eventor::Suspend()
{
  static const Exc_t _eh("Eventor::Suspend ");

  if(!bXMultix && mHost != mSaturn->GetSaturnInfo()) return;

  if(!bRunning) {
    ISwarn(_eh + "not running.");
    return;
  }

  if(bSuspended) {
    ISwarn(_eh + "already suspended.");
    return;
  }

  mSaturn->GetChaItOss()->Suspend(this);
}

void Eventor::Resume()
{
  static const Exc_t _eh("Eventor::Resume ");

  if(!bXMultix && mHost != mSaturn->GetSaturnInfo()) return;

  if(!bRunning) {
    ISwarn(_eh + "not running.");
    return;
  }

  if(!bSuspended) {
    ISwarn(_eh + "not paused.");
    return;
  }

  mSaturn->GetChaItOss()->Resume(this);
}

void Eventor::Reset()
{
  mTotalTime = mRunTime = 0;
  mBeatsDone = mLocBeatsDone = 0;
  mEventID      = 0;
  mInternalTime = 0;
  Stamp(FID());
}

void Eventor::Cancel()
{
  static const Exc_t _eh("Eventor::Cancel ");

  if(!bXMultix && mHost != mSaturn->GetSaturnInfo()) return;

  if(!bRunning) {
    ISwarn(_eh + "not running.");
    return;
  }

  mSaturn->GetChaItOss()->Cancel(this);
}

/**************************************************************************/

void Eventor::ResetRecursively()
{
  static const Exc_t _eh("Eventor::ResetRecursively ");

  if(bRunning)
    throw(_eh + "called during operation.");

  Reset();
  PARENT_GLASS::ResetRecursively();
}


/**************************************************************************/
/**************************************************************************/

void Eventor::SetHost(SaturnInfo* host)
{
  static const Exc_t _eh("Eventor::SetHost ");

  WriteLock();
  try {
    if(bRunning)
      throw(_eh + "cannot change host while thread is running.");
    set_link_or_die(mHost.ref_link(), host, FID());
  }
  catch(...) {
    WriteUnlock();
    throw;
  }
  WriteUnlock();
}

void Eventor::SetTrapAll()
{
  bTrapILL = bTrapBUS = bTrapFPE = bTrapSEGV = true;
  Stamp(FID());
}

/**************************************************************************/
// Time service for operators
/**************************************************************************/

Double_t Eventor::GetEventTime()
{
  return mTimeStack.back();
}

void Eventor::PushEventTime(Double_t time)
{
  mTimeStack.push_back(time);
}

void Eventor::PopEventTime()
{
  mTimeStack.pop_back();
}
 Eventor.cxx:1
 Eventor.cxx:2
 Eventor.cxx:3
 Eventor.cxx:4
 Eventor.cxx:5
 Eventor.cxx:6
 Eventor.cxx:7
 Eventor.cxx:8
 Eventor.cxx:9
 Eventor.cxx:10
 Eventor.cxx:11
 Eventor.cxx:12
 Eventor.cxx:13
 Eventor.cxx:14
 Eventor.cxx:15
 Eventor.cxx:16
 Eventor.cxx:17
 Eventor.cxx:18
 Eventor.cxx:19
 Eventor.cxx:20
 Eventor.cxx:21
 Eventor.cxx:22
 Eventor.cxx:23
 Eventor.cxx:24
 Eventor.cxx:25
 Eventor.cxx:26
 Eventor.cxx:27
 Eventor.cxx:28
 Eventor.cxx:29
 Eventor.cxx:30
 Eventor.cxx:31
 Eventor.cxx:32
 Eventor.cxx:33
 Eventor.cxx:34
 Eventor.cxx:35
 Eventor.cxx:36
 Eventor.cxx:37
 Eventor.cxx:38
 Eventor.cxx:39
 Eventor.cxx:40
 Eventor.cxx:41
 Eventor.cxx:42
 Eventor.cxx:43
 Eventor.cxx:44
 Eventor.cxx:45
 Eventor.cxx:46
 Eventor.cxx:47
 Eventor.cxx:48
 Eventor.cxx:49
 Eventor.cxx:50
 Eventor.cxx:51
 Eventor.cxx:52
 Eventor.cxx:53
 Eventor.cxx:54
 Eventor.cxx:55
 Eventor.cxx:56
 Eventor.cxx:57
 Eventor.cxx:58
 Eventor.cxx:59
 Eventor.cxx:60
 Eventor.cxx:61
 Eventor.cxx:62
 Eventor.cxx:63
 Eventor.cxx:64
 Eventor.cxx:65
 Eventor.cxx:66
 Eventor.cxx:67
 Eventor.cxx:68
 Eventor.cxx:69
 Eventor.cxx:70
 Eventor.cxx:71
 Eventor.cxx:72
 Eventor.cxx:73
 Eventor.cxx:74
 Eventor.cxx:75
 Eventor.cxx:76
 Eventor.cxx:77
 Eventor.cxx:78
 Eventor.cxx:79
 Eventor.cxx:80
 Eventor.cxx:81
 Eventor.cxx:82
 Eventor.cxx:83
 Eventor.cxx:84
 Eventor.cxx:85
 Eventor.cxx:86
 Eventor.cxx:87
 Eventor.cxx:88
 Eventor.cxx:89
 Eventor.cxx:90
 Eventor.cxx:91
 Eventor.cxx:92
 Eventor.cxx:93
 Eventor.cxx:94
 Eventor.cxx:95
 Eventor.cxx:96
 Eventor.cxx:97
 Eventor.cxx:98
 Eventor.cxx:99
 Eventor.cxx:100
 Eventor.cxx:101
 Eventor.cxx:102
 Eventor.cxx:103
 Eventor.cxx:104
 Eventor.cxx:105
 Eventor.cxx:106
 Eventor.cxx:107
 Eventor.cxx:108
 Eventor.cxx:109
 Eventor.cxx:110
 Eventor.cxx:111
 Eventor.cxx:112
 Eventor.cxx:113
 Eventor.cxx:114
 Eventor.cxx:115
 Eventor.cxx:116
 Eventor.cxx:117
 Eventor.cxx:118
 Eventor.cxx:119
 Eventor.cxx:120
 Eventor.cxx:121
 Eventor.cxx:122
 Eventor.cxx:123
 Eventor.cxx:124
 Eventor.cxx:125
 Eventor.cxx:126
 Eventor.cxx:127
 Eventor.cxx:128
 Eventor.cxx:129
 Eventor.cxx:130
 Eventor.cxx:131
 Eventor.cxx:132
 Eventor.cxx:133
 Eventor.cxx:134
 Eventor.cxx:135
 Eventor.cxx:136
 Eventor.cxx:137
 Eventor.cxx:138
 Eventor.cxx:139
 Eventor.cxx:140
 Eventor.cxx:141
 Eventor.cxx:142
 Eventor.cxx:143
 Eventor.cxx:144
 Eventor.cxx:145
 Eventor.cxx:146
 Eventor.cxx:147
 Eventor.cxx:148
 Eventor.cxx:149
 Eventor.cxx:150
 Eventor.cxx:151
 Eventor.cxx:152
 Eventor.cxx:153
 Eventor.cxx:154
 Eventor.cxx:155
 Eventor.cxx:156
 Eventor.cxx:157
 Eventor.cxx:158
 Eventor.cxx:159
 Eventor.cxx:160
 Eventor.cxx:161
 Eventor.cxx:162
 Eventor.cxx:163
 Eventor.cxx:164
 Eventor.cxx:165
 Eventor.cxx:166
 Eventor.cxx:167
 Eventor.cxx:168
 Eventor.cxx:169
 Eventor.cxx:170
 Eventor.cxx:171
 Eventor.cxx:172
 Eventor.cxx:173
 Eventor.cxx:174
 Eventor.cxx:175
 Eventor.cxx:176
 Eventor.cxx:177
 Eventor.cxx:178
 Eventor.cxx:179
 Eventor.cxx:180
 Eventor.cxx:181
 Eventor.cxx:182
 Eventor.cxx:183
 Eventor.cxx:184
 Eventor.cxx:185
 Eventor.cxx:186
 Eventor.cxx:187
 Eventor.cxx:188
 Eventor.cxx:189
 Eventor.cxx:190
 Eventor.cxx:191
 Eventor.cxx:192
 Eventor.cxx:193
 Eventor.cxx:194
 Eventor.cxx:195
 Eventor.cxx:196
 Eventor.cxx:197
 Eventor.cxx:198
 Eventor.cxx:199
 Eventor.cxx:200
 Eventor.cxx:201
 Eventor.cxx:202
 Eventor.cxx:203
 Eventor.cxx:204
 Eventor.cxx:205
 Eventor.cxx:206
 Eventor.cxx:207
 Eventor.cxx:208
 Eventor.cxx:209
 Eventor.cxx:210
 Eventor.cxx:211
 Eventor.cxx:212
 Eventor.cxx:213
 Eventor.cxx:214
 Eventor.cxx:215
 Eventor.cxx:216
 Eventor.cxx:217
 Eventor.cxx:218
 Eventor.cxx:219
 Eventor.cxx:220
 Eventor.cxx:221
 Eventor.cxx:222
 Eventor.cxx:223
 Eventor.cxx:224
 Eventor.cxx:225
 Eventor.cxx:226
 Eventor.cxx:227
 Eventor.cxx:228
 Eventor.cxx:229
 Eventor.cxx:230
 Eventor.cxx:231
 Eventor.cxx:232
 Eventor.cxx:233
 Eventor.cxx:234
 Eventor.cxx:235
 Eventor.cxx:236
 Eventor.cxx:237
 Eventor.cxx:238
 Eventor.cxx:239
 Eventor.cxx:240
 Eventor.cxx:241
 Eventor.cxx:242
 Eventor.cxx:243
 Eventor.cxx:244
 Eventor.cxx:245
 Eventor.cxx:246
 Eventor.cxx:247
 Eventor.cxx:248
 Eventor.cxx:249
 Eventor.cxx:250
 Eventor.cxx:251
 Eventor.cxx:252
 Eventor.cxx:253
 Eventor.cxx:254
 Eventor.cxx:255
 Eventor.cxx:256
 Eventor.cxx:257
 Eventor.cxx:258
 Eventor.cxx:259
 Eventor.cxx:260
 Eventor.cxx:261
 Eventor.cxx:262
 Eventor.cxx:263
 Eventor.cxx:264
 Eventor.cxx:265
 Eventor.cxx:266
 Eventor.cxx:267
 Eventor.cxx:268
 Eventor.cxx:269
 Eventor.cxx:270
 Eventor.cxx:271
 Eventor.cxx:272
 Eventor.cxx:273
 Eventor.cxx:274
 Eventor.cxx:275
 Eventor.cxx:276
 Eventor.cxx:277
 Eventor.cxx:278
 Eventor.cxx:279
 Eventor.cxx:280
 Eventor.cxx:281
 Eventor.cxx:282
 Eventor.cxx:283
 Eventor.cxx:284
 Eventor.cxx:285
 Eventor.cxx:286
 Eventor.cxx:287
 Eventor.cxx:288
 Eventor.cxx:289
 Eventor.cxx:290
 Eventor.cxx:291
 Eventor.cxx:292
 Eventor.cxx:293
 Eventor.cxx:294
 Eventor.cxx:295
 Eventor.cxx:296
 Eventor.cxx:297
 Eventor.cxx:298
 Eventor.cxx:299
 Eventor.cxx:300
 Eventor.cxx:301
 Eventor.cxx:302
 Eventor.cxx:303
 Eventor.cxx:304
 Eventor.cxx:305
 Eventor.cxx:306
 Eventor.cxx:307
 Eventor.cxx:308
 Eventor.cxx:309
 Eventor.cxx:310
 Eventor.cxx:311
 Eventor.cxx:312
 Eventor.cxx:313
 Eventor.cxx:314
 Eventor.cxx:315
 Eventor.cxx:316
 Eventor.cxx:317
 Eventor.cxx:318
 Eventor.cxx:319
 Eventor.cxx:320
 Eventor.cxx:321
 Eventor.cxx:322
 Eventor.cxx:323
 Eventor.cxx:324
 Eventor.cxx:325
 Eventor.cxx:326
 Eventor.cxx:327
 Eventor.cxx:328
 Eventor.cxx:329
 Eventor.cxx:330
 Eventor.cxx:331
 Eventor.cxx:332
 Eventor.cxx:333
 Eventor.cxx:334
 Eventor.cxx:335
 Eventor.cxx:336
 Eventor.cxx:337
 Eventor.cxx:338
 Eventor.cxx:339
 Eventor.cxx:340
 Eventor.cxx:341
 Eventor.cxx:342
 Eventor.cxx:343
 Eventor.cxx:344
 Eventor.cxx:345
 Eventor.cxx:346
 Eventor.cxx:347
 Eventor.cxx:348
 Eventor.cxx:349
 Eventor.cxx:350
 Eventor.cxx:351
 Eventor.cxx:352
 Eventor.cxx:353
 Eventor.cxx:354
 Eventor.cxx:355
 Eventor.cxx:356
 Eventor.cxx:357
 Eventor.cxx:358
 Eventor.cxx:359
 Eventor.cxx:360
 Eventor.cxx:361
 Eventor.cxx:362
 Eventor.cxx:363
 Eventor.cxx:364
 Eventor.cxx:365
 Eventor.cxx:366
 Eventor.cxx:367
 Eventor.cxx:368
 Eventor.cxx:369
 Eventor.cxx:370
 Eventor.cxx:371
 Eventor.cxx:372
 Eventor.cxx:373
 Eventor.cxx:374
 Eventor.cxx:375
 Eventor.cxx:376
 Eventor.cxx:377
 Eventor.cxx:378
 Eventor.cxx:379
 Eventor.cxx:380
 Eventor.cxx:381
 Eventor.cxx:382
 Eventor.cxx:383
 Eventor.cxx:384
 Eventor.cxx:385
 Eventor.cxx:386
 Eventor.cxx:387
 Eventor.cxx:388
 Eventor.cxx:389
 Eventor.cxx:390
 Eventor.cxx:391
 Eventor.cxx:392
 Eventor.cxx:393
 Eventor.cxx:394
 Eventor.cxx:395
 Eventor.cxx:396
 Eventor.cxx:397
 Eventor.cxx:398
 Eventor.cxx:399
 Eventor.cxx:400
 Eventor.cxx:401
 Eventor.cxx:402
 Eventor.cxx:403
 Eventor.cxx:404
 Eventor.cxx:405
 Eventor.cxx:406
 Eventor.cxx:407
 Eventor.cxx:408
 Eventor.cxx:409
 Eventor.cxx:410