mirror of https://github.com/BOINC/boinc.git
Update BasicApi.md file
Signed-off-by: Vitalii Koshura <lestat.de.lionkur@gmail.com>
parent
e02e5d6ba4
commit
676fe95ef3
256
BasicApi.md
256
BasicApi.md
|
@ -1,120 +1,116 @@
|
|||
[[PageOutline]]
|
||||
# The BOINC application programming interface (API)
|
||||
|
||||
The BOINC API is a set of C++ functions.
|
||||
Most of the functions have a C interface,
|
||||
so that they can be used from programs written in C and other languages.
|
||||
Unless otherwise specified, the functions return an integer error code;
|
||||
zero indicates success.
|
||||
To use the API include the header file:
|
||||
|
||||
#include "boinc_api.h"
|
||||
|
||||
```
|
||||
#include "boinc_api.h"
|
||||
```
|
||||
|
||||
BOINC applications may have an associate graphics program,
|
||||
which can act as a screensaver.
|
||||
The API for these graphics apps is [here](GraphicsApps).
|
||||
|
||||
# Initialization #init
|
||||
# Initialization
|
||||
|
||||
Initialization must be done before calling other BOINC functions.
|
||||
For sequential (single-threaded) apps, call
|
||||
|
||||
boinc_init();
|
||||
|
||||
```
|
||||
boinc_init();
|
||||
```
|
||||
|
||||
## Parallel apps
|
||||
# Parallel apps
|
||||
|
||||
If your uses multiple threads or processes for parallelism, initialize using
|
||||
|
||||
BOINC_OPTIONS options;
|
||||
|
||||
boinc_options_defaults(options);
|
||||
options.multi_thread = true; // if your app's main process uses multiple threads
|
||||
options.multi_process = true; // if your app uses multiple processes
|
||||
|
||||
boinc_init_options(&options);
|
||||
|
||||
```
|
||||
BOINC_OPTIONS options;
|
||||
|
||||
boinc_options_defaults(options);
|
||||
options.multi_thread = true; // if your app's main process uses multiple threads
|
||||
options.multi_process = true; // if your app uses multiple processes
|
||||
|
||||
boinc_init_options(&options);
|
||||
```
|
||||
Do this before creating any threads or processes, or storing the PID.
|
||||
|
||||
## GPU and coprocessor apps
|
||||
# GPU and coprocessor apps
|
||||
|
||||
If your app uses GPUs or coprocessors, initialize using
|
||||
|
||||
BOINC_OPTIONS options;
|
||||
|
||||
boinc_options_defaults(options);
|
||||
options.normal_thread_priority = true;
|
||||
boinc_init_options(&options);
|
||||
|
||||
```
|
||||
BOINC_OPTIONS options;
|
||||
|
||||
boinc_options_defaults(options);
|
||||
options.normal_thread_priority = true;
|
||||
boinc_init_options(&options);
|
||||
```
|
||||
On Windows, this causes the application to run at normal thread priority,
|
||||
so that the GPU will run at full speed even if the CPUs are loaded.
|
||||
# Termination
|
||||
When the application has completed it must call
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_finish(int status);
|
||||
|
||||
```c++
|
||||
int boinc_finish(int status);
|
||||
```
|
||||
|
||||
`status` is nonzero if an error was encountered.
|
||||
This call does not return.
|
||||
|
||||
Do *not* call `exit(0)`.
|
||||
Do **not** call `exit(0)`.
|
||||
If you do, BOINC will restart the app, which is probably not what you want.
|
||||
|
||||
Alternatively, if you want to show a message to the user
|
||||
(e.g. because of an error condition that the user can remedy) use
|
||||
|
||||
boinc_finish_message(int status, const char* msg, bool is_notice);
|
||||
|
||||
If *is_notice* is true, the message will be shown as a notice in the GUI
|
||||
```
|
||||
boinc_finish_message(int status, const char* msg, bool is_notice);
|
||||
```
|
||||
If **is_notice** is true, the message will be shown as a notice in the GUI
|
||||
(works with 7.5+ clients; for others, no message will be shown).
|
||||
|
||||
# Resolving file names #filenames
|
||||
# Resolving file names
|
||||
|
||||
Applications that use named input or output files must call
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_resolve_filename(char *logical_name, char *physical_name, int len);
|
||||
|
||||
```c++
|
||||
int boinc_resolve_filename(char *logical_name, char *physical_name, int len);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_resolve_filename_s(char *logical_name, std::string& physical_name);
|
||||
|
||||
```c++
|
||||
### int boinc_resolve_filename_s(char *logical_name, std
|
||||
string& physical_name);
|
||||
```
|
||||
|
||||
to convert logical file names to physical names. For example, instead of
|
||||
|
||||
|
||||
#!c++
|
||||
f = fopen("my_file", "r");
|
||||
|
||||
```c++
|
||||
f = fopen("my_file", "r");
|
||||
```
|
||||
|
||||
the application might use
|
||||
|
||||
|
||||
#!c++
|
||||
string resolved_name;
|
||||
retval = boinc_resolve_filename_s("my_file", resolved_name);
|
||||
if (retval) fail("can't resolve filename");
|
||||
f = boinc_fopen(resolved_name.c_str(), "r");
|
||||
|
||||
```c++
|
||||
string resolved_name;
|
||||
retval = boinc_resolve_filename_s("my_file", resolved_name);
|
||||
if (retval) fail("can't resolve filename");
|
||||
f = boinc_fopen(resolved_name.c_str(), "r");
|
||||
```
|
||||
|
||||
Don't use `boinc_resolve_filename()` for files with the *copy_file* attribute,
|
||||
Don't use `boinc_resolve_filename()` for files with the **copy_file** attribute,
|
||||
or for temporary files.
|
||||
It must be used for all other input or output files specified in the job templates,
|
||||
or files that are part of the application version.
|
||||
|
||||
# I/O wrappers #fopen
|
||||
# I/O wrappers
|
||||
|
||||
Applications should replace `fopen()` calls with
|
||||
|
||||
|
||||
#!c++
|
||||
boinc_fopen(char* path, char* mode);
|
||||
|
||||
```c++
|
||||
boinc_fopen(char* path, char* mode);
|
||||
```
|
||||
|
||||
This deals with platform-specific problems.
|
||||
On Windows, where security and indexing programs can briefly lock files,
|
||||
|
@ -122,11 +118,11 @@ On Windows, where security and indexing programs can briefly lock files,
|
|||
On Unix, where signals can cause `fopen()` to fail with `EINTR`,
|
||||
`boinc_fopen` checks for this and does a few retries; it also sets the 'close-on-exec' flag.
|
||||
|
||||
# Checkpointing #checkpointing
|
||||
# Checkpointing
|
||||
|
||||
Long jobs may want to periodically
|
||||
write the current state of the computation to disk.
|
||||
This is known as *checkpointing*.
|
||||
This is known as **checkpointing**.
|
||||
The checkpoint file must include everything required to restart the computation
|
||||
at the same point.
|
||||
On startup, the application reads the checkpoint file to determine where to begin computation.
|
||||
|
@ -137,23 +133,21 @@ Most applications are able to checkpoint only at specific points,
|
|||
e.g. at the end the outer loop.
|
||||
Whan the application is at such a point, it must call
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_time_to_checkpoint();
|
||||
|
||||
```c++
|
||||
int boinc_time_to_checkpoint();
|
||||
```
|
||||
|
||||
If this returns nonzero (True) then the application should checkpoint immediately
|
||||
(i.e., write the state file and flush all output files), then call
|
||||
|
||||
|
||||
#!c++
|
||||
void boinc_checkpoint_completed();
|
||||
|
||||
```c++
|
||||
void boinc_checkpoint_completed();
|
||||
```
|
||||
|
||||
`boinc_time_to_checkpoint()` is fast,
|
||||
so it can be called frequently (hundreds or thousands of times a second).
|
||||
|
||||
*boinc_time_to_checkpoint* returns true only when sufficient time
|
||||
**boinc_time_to_checkpoint** returns true only when sufficient time
|
||||
has passed since the last checkpoint.
|
||||
This minimum interval is the maximum of:
|
||||
|
||||
|
@ -161,9 +155,9 @@ This minimum interval is the maximum of:
|
|||
(e.g. laptop users might want to checkpoint infrequently).
|
||||
* An optional application-supplied, specified by calling
|
||||
|
||||
|
||||
boinc_set_min_checkpoint_period(int nsecs);
|
||||
|
||||
```
|
||||
boinc_set_min_checkpoint_period(int nsecs);
|
||||
```
|
||||
|
||||
If you're using replication, make sure your application generates the same results
|
||||
regardless of where and how often it restarts.
|
||||
|
@ -173,64 +167,61 @@ This requires:
|
|||
* If your app uses random numbers, save and restore the state of the RNG.
|
||||
If you use rand(), you can do this by surrounding every boinc_time_to_checkpoint()
|
||||
with the following:
|
||||
|
||||
int x = rand();
|
||||
if (boinc_time_to_checkpoint()) {
|
||||
...
|
||||
}
|
||||
srand(x);
|
||||
|
||||
```
|
||||
int x = rand();
|
||||
if (boinc_time_to_checkpoint()) {
|
||||
...
|
||||
}
|
||||
srand(x);
|
||||
```
|
||||
Write x to the checkpoint file,
|
||||
and do a srand(x) when restarting from a checkpoint.
|
||||
|
||||
# Critical sections #critical_sections
|
||||
# Critical sections
|
||||
|
||||
|
||||
#!c++
|
||||
void boinc_begin_critical_section();
|
||||
void boinc_end_critical_section();
|
||||
|
||||
```c++
|
||||
void boinc_begin_critical_section();
|
||||
void boinc_end_critical_section();
|
||||
```
|
||||
|
||||
Call these around code segments during which you don't want to be
|
||||
suspended or killed by the core client.
|
||||
Since r14694, critical sections are reentrant.
|
||||
This means that you can begin critical section multiple times,
|
||||
but each `begin` must have a matching `end` call.
|
||||
but each ```begin``` must have a matching ```end``` call.
|
||||
|
||||
*NOTE:* This is done automatically while checkpointing.
|
||||
**NOTE:** This is done automatically while checkpointing.
|
||||
|
||||
# Atomic file update
|
||||
|
||||
To facilitate atomic checkpoint,
|
||||
an application can write to output and state files using the `MFILE` class.
|
||||
|
||||
|
||||
#!c++
|
||||
class MFILE {
|
||||
public:
|
||||
int open(char* path, char* mode);
|
||||
int _putchar(char);
|
||||
int puts(char*);
|
||||
int printf(char* format, ...);
|
||||
size_t write(const void* buf, size_t size, size_t nitems);
|
||||
int close();
|
||||
int flush();
|
||||
};
|
||||
|
||||
```c++
|
||||
class MFILE {
|
||||
public:
|
||||
int open(char* path, char* mode);
|
||||
int _putchar(char);
|
||||
int puts(char*);
|
||||
int printf(char* format, ...);
|
||||
size_t write(const void* buf, size_t size, size_t nitems);
|
||||
int close();
|
||||
int flush();
|
||||
};
|
||||
```
|
||||
|
||||
MFILE buffers data in memory and writes to disk only on `flush()` or `close()`.
|
||||
This lets you write output files and state files more or less atomically.
|
||||
|
||||
|
||||
# Reporting progress #progress
|
||||
# Reporting progress
|
||||
|
||||
The BOINC Manager displays the percent done of tasks in progress.
|
||||
To keep this display current, an application should periodically call
|
||||
|
||||
|
||||
#!c++
|
||||
boinc_fraction_done(double fraction_done);
|
||||
|
||||
```c++
|
||||
boinc_fraction_done(double fraction_done);
|
||||
```
|
||||
|
||||
The `fraction_done` argument is an estimate of the workunit fraction complete (from 0 to 1).
|
||||
This function is fast and can be called frequently (once per second or more).
|
||||
|
@ -244,22 +235,22 @@ If your application can supply an accurate fraction done, set the
|
|||
|
||||
# Timing information
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_wu_cpu_time(double &cpu_time);
|
||||
|
||||
```c++
|
||||
int boinc_wu_cpu_time(double &cpu_time);
|
||||
```
|
||||
|
||||
gets the total CPU time (from the beginning of the work unit, not just since the last restart).
|
||||
|
||||
|
||||
double boinc_elapsed_time();
|
||||
|
||||
```
|
||||
double boinc_elapsed_time();
|
||||
```
|
||||
returns the elapsed runtime (i.e. wall-clock time during which the job
|
||||
was not suspended) since the start of the current episode.
|
||||
The elapsed time from earlier episodes is in APP_INIT_DATA::starting_elapsed_time
|
||||
### The elapsed time from earlier episodes is in APP_INIT_DATA
|
||||
starting_elapsed_time
|
||||
(only from 6.10+ clients).
|
||||
|
||||
# Standalone mode #standalone
|
||||
# Standalone mode
|
||||
|
||||
BOINC applications can be run in "standalone" mode for testing,
|
||||
or under the control of the BOINC client.
|
||||
|
@ -269,21 +260,19 @@ if the application is running standalone.
|
|||
To determine if the application is running in standalone mode or
|
||||
under the control of the BOINC client, call
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_is_standalone(void);
|
||||
|
||||
```c++
|
||||
int boinc_is_standalone(void);
|
||||
```
|
||||
|
||||
This returns non-zero (True) if the application is running standalone,
|
||||
and zero (False) if the application is running under the control of the BOINC client.
|
||||
|
||||
# Registering a timer handler #timer
|
||||
# Registering a timer handler
|
||||
|
||||
|
||||
#!c++
|
||||
typedef void (*FUNC_PTR)();
|
||||
void boinc_register_timer_callback(FUNC_PTR);
|
||||
|
||||
```c++
|
||||
typedef void (*FUNC_PTR)();
|
||||
void boinc_register_timer_callback(FUNC_PTR);
|
||||
```
|
||||
|
||||
This registers a timer handler function,
|
||||
which will be called once per second.
|
||||
|
@ -293,17 +282,16 @@ which will be called once per second.
|
|||
If an application is unable to run because of a transient condition,
|
||||
it should call
|
||||
|
||||
|
||||
#!c++
|
||||
int boinc_temporary_exit(int delay, const char* reason=NULL, bool is_notice=false);
|
||||
|
||||
```c++
|
||||
int boinc_temporary_exit(int delay, const char* reason=NULL, bool is_notice=false);
|
||||
```
|
||||
|
||||
This will exit the application and tell the BOINC client to restart it
|
||||
again in at least *delay* seconds.
|
||||
again in at least **delay** seconds.
|
||||
(This works with 6.10.25+ client;
|
||||
on other clients, it will potentially restart immediately).
|
||||
*Reason*, if supplied, is shown to the user as the explanation for the deferral.
|
||||
If *is_notice* is true, it's shown as a notice
|
||||
**Reason**, if supplied, is shown to the user as the explanation for the deferral.
|
||||
If **is_notice** is true, it's shown as a notice
|
||||
(this should be used only for conditions that the user can fix).
|
||||
|
||||
Examples:
|
||||
|
|
Loading…
Reference in New Issue