w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
RtclAttnShuttle.cpp
Go to the documentation of this file.
1// $Id: RtclAttnShuttle.cpp 1186 2019-07-12 17:49:59Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2013-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2019-02-23 1114 1.1.4 use std::bind instead of lambda
8// 2018-12-18 1089 1.1.3 use c++ style casts
9// 2018-12-15 1082 1.1.2 use lambda instead of boost::bind
10// 2018-10-27 1059 1.1.1 coverity fixup (uncaught exception in dtor)
11// 2014-12-30 625 1.1 adopt to Rlink V4 attn logic
12// 2014-11-08 602 1.0.3 cast int first to ptrdiff_t, than to ClientData
13// 2014-08-22 584 1.0.2 use nullptr
14// 2013-05-20 521 1.0.1 Setup proper Tcl channel options
15// 2013-03-01 493 1.0 Initial version
16// 2013-01-12 475 0.5 First draft
17// ---------------------------------------------------------------------------
18
23#include <unistd.h>
24#include <errno.h>
25
26#include <functional>
27
29#include "librtools/Rtools.hpp"
30
31#include "RtclAttnShuttle.hpp"
32
33using namespace std;
34using namespace std::placeholders;
35
41// all method definitions in namespace Retro
42namespace Retro {
43
44//------------------------------------------+-----------------------------------
46
47RtclAttnShuttle::RtclAttnShuttle(uint16_t mask, Tcl_Obj* pobj)
48 : fpServ(nullptr),
49 fpInterp(nullptr),
50 fFdPipeRead(-1),
51 fFdPipeWrite(-1),
52 fShuttleChn(0),
53 fMask(mask),
54 fpScript(pobj)
55{
56 int pipefd[2];
57 int irc = ::pipe(pipefd);
58 if (irc < 0)
59 throw Rexception("RtclAttnShuttle::<ctor>", "pipe() failed: ", errno);
60 fFdPipeRead = pipefd[0];
61 fFdPipeWrite = pipefd[1];
62}
63
64//------------------------------------------+-----------------------------------
66
68{
69 Rtools::Catch2Cerr(__func__, [this](){ Remove();} );
70 ::close(fFdPipeWrite);
71 ::close(fFdPipeRead);
72}
73
74//------------------------------------------+-----------------------------------
76
77void RtclAttnShuttle::Add(RlinkServer* pserv, Tcl_Interp* interp)
78{
79 // connect to RlinkServer
80 pserv->AddAttnHandler(bind(&RtclAttnShuttle::AttnHandler, this, _1),
81 fMask, this);
82 fpServ = pserv;
83
84 // connect to Tcl
85 // cast first to ptrdiff_t to promote to proper int size
86 fShuttleChn = Tcl_MakeFileChannel(reinterpret_cast<ClientData>(fFdPipeRead),
87 TCL_READABLE);
88
89 Tcl_SetChannelOption(nullptr, fShuttleChn, "-buffersize", "64");
90 Tcl_SetChannelOption(nullptr, fShuttleChn, "-encoding", "binary");
91 Tcl_SetChannelOption(nullptr, fShuttleChn, "-translation", "binary");
92
93 Tcl_CreateChannelHandler(fShuttleChn, TCL_READABLE,
94 reinterpret_cast<Tcl_FileProc*>(ThunkTclChannelHandler),
95 reinterpret_cast<ClientData>(this));
96
97 fpInterp = interp;
98 return;
99}
100
101//------------------------------------------+-----------------------------------
103
105{
106 // disconnect from RlinkServer
107 if (fpServ) {
109 fpServ = nullptr;
110 }
111 // disconnect from Tcl
112 if (fpInterp) {
113 Tcl_DeleteChannelHandler(fShuttleChn,
114 reinterpret_cast<Tcl_FileProc*>(ThunkTclChannelHandler),
115 reinterpret_cast<ClientData>(this));
116 Tcl_Close(fpInterp, fShuttleChn);
117 fpInterp = nullptr;
118 }
119
120 return;
121}
122
123//------------------------------------------+-----------------------------------
125
127{
128 fpServ->GetAttnInfo(args);
129
130 uint16_t apat = args.fAttnPatt & args.fAttnMask;
131 int irc = ::write(fFdPipeWrite, &apat, sizeof(apat));
132 if (irc < 0)
133 throw Rexception("RtclAttnShuttle::AttnHandler()",
134 "write() failed: ", errno);
135
136 return 0;
137}
138
139//------------------------------------------+-----------------------------------
141
143{
144 uint16_t apat;
145 Tcl_ReadRaw(fShuttleChn, reinterpret_cast<char*>(&apat), sizeof(apat));
146 // FIXME_code: handle return code
147
148 Tcl_SetVar2Ex(fpInterp, "Rlink_attnbits", nullptr,
149 Tcl_NewIntObj(int(apat)), 0);
150 // FIXME_code: handle return code
151
152 Tcl_EvalObjEx(fpInterp, fpScript, TCL_EVAL_GLOBAL);
153 // FIXME_code: handle return code
154 return;
155}
156
157//------------------------------------------+-----------------------------------
159
160void RtclAttnShuttle::ThunkTclChannelHandler(ClientData cdata, int mask)
161{
162 reinterpret_cast<RtclAttnShuttle*>(cdata)->TclChannelHandler(mask);
163 return;
164}
165
166} // end namespace Retro
FIXME_docs.
Definition: Rexception.hpp:29
void AddAttnHandler(attnhdl_t &&attnhdl, uint16_t mask, void *cdata=nullptr)
FIXME_docs.
void GetAttnInfo(AttnArgs &args, RlinkCommandList &clist)
FIXME_docs.
void RemoveAttnHandler(uint16_t mask, void *cdata=nullptr)
FIXME_docs.
void Add(RlinkServer *pserv, Tcl_Interp *interp)
FIXME_docs.
uint16_t fMask
attn mask
void TclChannelHandler(int mask)
FIXME_docs.
static void ThunkTclChannelHandler(ClientData cdata, int mask)
FIXME_docs.
RlinkServer * fpServ
RlinkServer used.
Tcl_Interp * fpInterp
Tcl interpreter used.
RtclOPtr fpScript
Tcl handler script (as Tcl_Obj)
int AttnHandler(RlinkServer::AttnArgs &args)
FIXME_docs.
RtclAttnShuttle(uint16_t mask, Tcl_Obj *pobj)
constructor
int fFdPipeWrite
attn pipe write fd
Tcl_Channel fShuttleChn
Tcl channel.
void Remove()
FIXME_docs.
int fFdPipeRead
attn pipe read fd
void Catch2Cerr(const char *msg, std::function< void()> func)
FIXME_docs.
Definition: Rtools.cpp:170
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47
uint16_t fAttnPatt
in: current attention pattern
Definition: RlinkServer.hpp:52
uint16_t fAttnMask
in: handler attention mask
Definition: RlinkServer.hpp:53