forked from FreeFem/FreeFem-sources
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathffapi.cpp
323 lines (272 loc) · 9.41 KB
/
ffapi.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/// \file
/// ======================================================================
/// Written by Antoine Le Hyaric
/// Laboratoire Jacques-Louis Lions
/// Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
/// http://www.ljll.math.upmc.fr/lehyaric
/// ======================================================================
/// This file is part of Freefem++
///
/// Freefem++ is free software; you can redistribute it and/or modify
/// it under the terms of the GNU Lesser General Public License as
/// published by the Free Software Foundation; either version 2.1 of
/// the License, or (at your option) any later version.
///
/// Freefem++ 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 Lesser General Public License for more details.
///
/// You should have received a copy of the GNU Lesser General Public
/// License along with Freefem++; if not, write to the Free Software
/// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
/// 02110-1301 USA
/// ======================================================================
/// headeralh cpp freefem start=21/01/10 upmc
// Proposed FreeFem++ Application Programming Interface
// ----------------------------------------------------
#ifdef WITH_PETSC
#include <petsc.h>
#endif
// headerfilter [[shell:headerfilter '../../ff/src/fflib/ffapi.cpp']] [[file:~/alh/bin/headerfilter]]
#include "ffapi.hpp" // [[file:ffapi.hpp]] found by [[file:~/alh/bin/headerfilter]]
#include <cstdlib>
#ifdef FFLANG
#include "socket.hpp"
#include "spawn.hpp"
#include "buffer.hpp" // [[file:~/ffcs/src/buffer.hpp::Buffer]]
#endif
#include <iostream>
#include <cstdio>
#ifndef FFLANG
#include <cstdio>
#endif
#ifdef FFLANG
#include "options.hpp"
#include <stdlib.h>
#endif
#ifndef FFLANG
#ifdef _WIN32
#include <fcntl.h>
#endif
#endif
#ifndef FFLANG
#ifdef PARALLELE
#include "mpi.h"
#endif
#endif
extern long verbosity ;
// FFCS-specific implementations for the FF API
// --------------------------------------------
/// <<FFLANG>> defined means that FFCS is being compiled. I am fairly confident that FFCS will not be defined while
/// compiling the original FF.
/// Need to choose a non-zero stream number because FF will check it (as global variable ThePlotStream)
#define FFAPISTREAM 1
/// if FFCS is around, we need to bufferize all communications to avoid mixing up CMD_FFG and CMD_STDOUT messages
#ifdef FFLANG
void bufferwrite(const char *b,const int l){
Socket::dialoglock->WAIT(); // need #include "socket.hpp"
// thank to the buffering, there is only one CMD_FFG tag for multiple visualization data items.
onlyffsock()<<CMD_FFG; // need #include "spawn.hpp"
onlyffsock()<<l;
// this call contains the socket MAGIC number
onlyffsock().bufferedwrite(static_cast<const char*>(b),l);
Socket::dialoglock->Free();
}
Buffer buffer(NULL,bufferwrite); // need #include "buffer.hpp" // [[file:~/ffcs/src/buffer.hpp::Buffer]]
#endif
// allocation/definition of all ffapi in Global.cpp
namespace ffapi{
// Get a pointer to the local cin/cout (which is distinct from ffcs's stdin/stdout under Windows because each DLL owns
// separate cin/cout objects).
// need #include <iostream>
static std::istream *ffapi_cin(){return &std::cin;}
static std::ostream *ffapi_cout(){return &std::cout;}
static std::ostream *ffapi_cerr(){return &std::cerr;}
// FFCS - ::stdout not accepted under mingw32
// need #include <cstdio>
static FILE *ffapi_ffstdout(){return stdout;}
static FILE *ffapi_ffstderr(){return stderr;}
static FILE *ffapi_ffstdin(){return stdin;}
static void ffapi_newplot(){}
FILE *ffapi_ff_popen(const char *command, const char *type){
#ifdef FFLANG
// this happens right at the begining of FF, so the socket
// communication must not be started yet (only when actual
// visualization data needs to be transfered).
PROGRESS;
return (FILE*)FFAPISTREAM;
#else
// need #include <cstdio>
FILE *f= popen(command,type);
if( f!=0) {
// ne marche pas car ffglut plante si flux vide
// int ppok=pclose(f);
// f =0;
// if(ppok==0)
// f= popen(command,type);
// else
// std::cerr << " fopen ok but plose bug ! =" << ppok << "\n";
}
if( f==0) {
std::cerr << "Error: popen " << f << " " << command << " " << type << std::endl;
exit(1); }
return f;
#endif
}
// <<ffapi_ff_pclose>>
static int ffapi_ff_pclose(FILE *stream){
#ifdef FFLANG
// nothing to close in FFCS
return 0;
#else
return pclose(stream);
#endif
}
static size_t ffapi_fwriteinit(const void *ptr, size_t size, size_t nmemb,FILE *stream){
// printf() is useful for debug because it is not redirected through
// the FFCS socket. But it is asynchronous with cout so it may end up
// in the middle of the lines checked by test/compare. So deactivate
// it by default.
#ifdef DEBUG_FFAPI
#ifdef FFLANG
printf("debug: ffapi: using TCP sockets\n");
#else
printf("debug: ffapi: using an anonymous pipe\n");
#endif // FFLANG
#endif // DEBUG_FFAPI
#ifdef FFLANG
// Ask FFCS to analyze the visualization flux header. I could just skip this stage, but it will be useful to check
// the coherency between FFCS and FF when FF evolves in the future.
Socket::dialoglock->WAIT();
onlyffsock()<<CMD_FFGINIT;
Socket::dialoglock->Free();
#endif
return ff_fwrite(ptr,size,nmemb,stream);
}
static size_t ffapi_ff_fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream){
#ifdef FFLANG
// if the ffsock pointer is null here, it means that the pointer exported from the FFCS shared library is not a
// valid one (this has been the case with Windows DLLs in the past).
// we won't make use of the stream, but make sure that the call from
// FF is coherent with what we know.
assert(stream==(FILE*)FFAPISTREAM);
buffer.write(static_cast<const char*>(ptr),size*nmemb);
// stops the server flux at one precise point (point value expressed during a previous crash while reading server
// data in the client in visudata.cpp). Use abort() to call the debugger (which can display the call stack and show
// where the problematic pipe value came from).
// need #include "options.hpp"
if(options->AbortFFGraphicsDataAt==buffer.getpoint())abort(); // need #include <stdlib.h>
#else
fwrite(ptr,size,nmemb,stream);
#endif
return 0;
}
static int ffapi_ff_fflush(FILE *stream){
#ifdef FFLANG
assert(stream==(FILE*)FFAPISTREAM);
// we need to flush both the buffer and the socket to avoid a separate callback for flush in the buffer
buffer.flush();
// ff_fflush() is used by FF only at the end of a plot, so we can use this location to send a marker for the
// sequential java client to deal with one complete plot at a time.
Socket::dialoglock->WAIT();
onlyffsock()<<CMD_FFGEND;
onlyffsock().writeflush();
Socket::dialoglock->Free();
#else
fflush(stream);
#endif
return 0;
}
static int ffapi_ff_ferror(FILE *stream){
#ifndef FFLANG
return ferror(stream);
#else
return 0;
#endif
}
static int ffapi_ff_feof(FILE *stream){
#ifndef FFLANG
return feof(stream);
#else
return 0;
#endif
}
static void ffapi_wintextmode(FILE *f){
#ifndef FFLANG
#ifdef _WIN32
// need #include <fcntl.h>
_setmode(fileno(f),O_TEXT);
#endif
#endif
}
static void ffapi_winbinmode(FILE *f){
#ifndef FFLANG
#ifdef _WIN32
_setmode(fileno(f),O_BINARY);
#endif
#endif
}
static void ffapi_mpi_init(int &argc, char** &argv){
/// only call MPI_Init() if this has not already been done in [[file:~/ffcs/src/server.cpp]]
#ifndef FFLANG
#ifdef PARALLELE
// need #include "mpi.h"
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
if(provided < MPI_THREAD_SERIALIZED) {
MPI_Comm_rank(MPI_COMM_WORLD, &provided);
if(provided == 0)
std::cout << "MPI_THREAD_SERIALIZED not supported !" << std::endl;
}
#ifdef WITH_PETSCxxxxx
PetscInitialize(&argc, &argv, 0, "");
#endif
#endif
#endif
}
static void ffapi_mpi_finalize(){
#ifndef FFLANG
#ifdef PARALLELE
#ifdef WITH_PETSCxxxxxxxx
PetscFinalize();
#endif
MPI_Finalize();
#endif
#endif
}
static bool ffapi_protectedservermode(){
#ifdef FFLANG
return !options->LocalClient;
#else
return false;
#endif
}
// <<init>> [[file:ffapi.hpp::init]] called by [[file:../lglib/mymain.cpp::ffapi::init]]
void init(){
ffapi::cin = ffapi::ffapi_cin;
ffapi::cout = ffapi::ffapi_cout;
ffapi::cerr = ffapi::ffapi_cerr;
ffapi::ffstdout = ffapi::ffapi_ffstdout;
ffapi::ffstderr = ffapi::ffapi_ffstderr;
ffapi::ffstdin = ffapi::ffapi_ffstdin;
ffapi::newplot = ffapi::ffapi_newplot;
ffapi::ff_popen = ffapi::ffapi_ff_popen;
ffapi::ff_pclose = ffapi::ffapi_ff_pclose; // <<ff_pclose>>
ffapi::fwriteinit = ffapi::ffapi_fwriteinit;
ffapi::ff_fwrite = ffapi::ffapi_ff_fwrite;
ffapi::ff_fflush = ffapi::ffapi_ff_fflush;
ffapi::ff_ferror = ffapi::ffapi_ff_ferror;
ffapi::ff_feof = ffapi::ffapi_ff_feof;
ffapi::wintextmode = ffapi::ffapi_wintextmode;
ffapi::winbinmode = ffapi::ffapi_winbinmode;
ffapi::mpi_init = ffapi::ffapi_mpi_init;
ffapi::mpi_finalize = ffapi::ffapi_mpi_finalize;
ffapi::protectedservermode = ffapi::ffapi_protectedservermode;
}
}
/// Local Variables:
/// mode:c++
/// ispell-local-dictionary:"british"
/// coding:utf-8
/// End: