/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "native-threads.h"
#include "exceptions.h"
#include "log.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

/* XXX Dummy method to avoid linking with libruntime */
void LOG_log(char *log, int level, char *msg_format, ...) {}
void throw_Exception(JNIEnv *env, const char *name,const char *msg) {}

/* This test must match the one on dynamic_loading.c */
#if (!defined(HAVE_DLL)) || defined PROFILING
int sysres_mappings = 0;
int java_util_mappings = 0;
int java_util_zip_mappings = 0;
int java_lang_mappings = 0;
int num_java_util_mappings = 0;
int num_java_lang_mappings = 0;
int num_java_net_mappings = 0;
int java_io_mappings = 0;
int java_net_mappings = 0;
int num_java_util_zip_mappings = 0;
int num_sysres_mappings = 0;
int num_java_io_mappings = 0;
#endif

static HMonitor monitor;
static int stock = 0;

static HMonitor done;
static int consumed = 0;
static const int consume = 20000;

#define PRODUCER 0
#define CONSUMER 1

static void producer(void)
{
  printf ("starting producer\n");
  while (1) {
    MONITOR_enter(monitor);

    if (stock > 5)
      MONITOR_wait(monitor);
    assert(stock <= 5);

    printf ("producing stock=%d\n", stock);
    fflush(NULL);

    stock++;
    MONITOR_notifyOne(monitor);
    MONITOR_exit(monitor);
  }
}
static void consumer(void)
{
  printf ("starting consumer\n");
  while (1) {
    MONITOR_enter(monitor);
    if (stock <= 0)
      MONITOR_wait(monitor);
    assert(stock > 0);

    printf ("consuming stock=%d\n", stock);
    fflush(NULL);
    stock--;
    consumed++;

    MONITOR_notifyOne(monitor);
    MONITOR_exit(monitor);
    if (consumed > consume) {
      MONITOR_enter(done);
      MONITOR_notifyOne(done);
      MONITOR_exit(done);
      break;
    }
  }    
}

static void*
thread_func(void* arg)
{
  int type = (int)arg;
  if (type == CONSUMER)
    consumer();
  else
    producer();

  /* NOTREACHED */
  return NULL;
}

int
main(int argc,
     char **argv)
{
  time_t start = time(NULL);
  time_t end;
  monitor = MONITOR_create();
  done = MONITOR_create();

  THREAD_start(thread_func, (void*)CONSUMER, 0, 0);
  THREAD_start(thread_func, (void*)PRODUCER, 0, 0);

  MONITOR_enter(done);
  MONITOR_wait(done);
  MONITOR_exit(done);
  end = time(NULL);
  printf("Done with %d consumes in %d seconds\n", consume, (int)(end - start));
  return 0;
}
