/*
 * Example of coupling c program and freemfem++ script
 * with mmap and semaphore
 *
 * the c code is    :   ffmaster.c
 * the ff++ code is : ffslave.edp
 * and here FreeFem++ is a slave process
 * the compile step is
 *
 * cc -c libff-mmap-semaphore.c
 # on linux, unix, 
 * cc ffmaster.c -o ffmaster  libff-mmap-semaphore.o -g
 # on win32 
 * cc ffmaster.c -o ffmaster  libff-mmap-semaphore.o -g  ../../3rdparty/lib/libpthread-google.a

 #build the freefem++ plugin
 * ff-c++ -auto ff-mmap-semaphore.cpp
 # launch
 # ./ffmaster
 #
 #
 # F. Hecht Feb. 2018   Frederic.Hecht@upmc.fr
 */

/*
 *
 * 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
 */

#include "libff-mmap-semaphore.h"
#if defined ( _WIN32 )
#  include <windows.h>
#  include <process.h>
#  define NO_STDIO_REDIRECT
#else
# include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>


ff_Psem sem_ff, sem_c;    // the semaphore for mutex
/*
 * Psemaphore smff("ff-slave");
 * Psemaphore smc("ff-master");
 * Pmmap sharedata("shared-data");
 *
 */
int main(int argc, const char **argv) {
  int debug = 0;
  ff_Pmmap shd;
  double cff, rff;
  long status;
  int i, ret;


  if (argc > 1) {
    debug = atoi(argv[1]);
  }

  ff_mmap_sem_verb = debug;

  sem_ff = ffsem_malloc( );
  sem_c = ffsem_malloc( );
  shd = ffmmap_malloc( );

  ffsem_init(sem_ff, "ff-slave1", 1);
  ffsem_init(sem_c, "ff-master1", 1);
  ffmmap_init(shd, "shared-data", 1024);

  status = 1;
  ffmmap_write(shd, &status, sizeof(status), 8);
  ffmmap_msync(shd, 0, 32);

  char ff[1024];
#ifdef _WIN32
  sprintf( ff, "%d", debug );
  ret = spawnl( P_NOWAIT,
                "..\\FreeFem++.exe",
                "..\\FreeFem++.exe",
                "..\\examples\\plugin\\ffslave.edp",
                "-nw", "-ns", "-v", ff, NULL );
#else
  sprintf(ff, "FreeFem++ /usr/share/doc/freefem++/examples/plugin/ffslave.edp -nw -ns -v %d&", debug);
  ret = system(ff);    // Lauch FF++ in batch no graphique
#endif
  if (ret == -1) printf("system function error\n");
  if (debug) {
    printf(" cc: before wait\n");
  }

  if (debug) {
    printf(" cc: before wait 0 ff\n");
  }

  ffsem_wait(sem_ff);

  for (i = 0; i < 10; ++i) {
    printf(" iter : %d \n", i);
    cff = 10 + i;
    ffmmap_write(shd, &cff, sizeof(cff), 0);
    ffsem_post(sem_c);

    if (debug) {
      printf(" cc: before wait 2\n");
    }

    ffsem_wait(sem_ff);
    ffmmap_read(shd, &rff, sizeof(rff), 16);
    printf(" iter = %d rff= %f\n", i, rff);
  }

  status = 0;    // Fin
  ffmmap_write(shd, &status, sizeof(status), 8);
  ffsem_post(sem_c);
  printf("Fin Master \n");
  ffsem_wait(sem_ff);
  ffsem_del(sem_ff);
  ffsem_del(sem_c);
  ffmmap_del(shd);
  return 0;
}
