// This may look like C code, but it is really -*- C++ -*-

#include <Magick++.h>
#include <iostream>
#include <list>

using namespace std;

using namespace Magick;

Image source;
void * testthread(void * data) {
  char num=static_cast<char>(reinterpret_cast<long>(data));
  cout << "thread " << num << " started" << endl;

  // Wait a bit, so all threads have a chance to start
  sleep(1);
  for (int i=0; i < 50; ++i) {
    
    // Make thread-private copy of source image.
    Image image(source);
    
    // Here, the image should be really copied.
    image.zoom(Geometry((rand()%300)+50,(rand()%300)+50));

    // Each thread has its own Blob to write to.
    Blob blob2;
    
    // And write to private blob.
    image.write( &blob2 );
    cout << "Thread " << num << ": Blob-Length " << blob2.length() << endl;
  }
  return NULL;
}

int main( int /*argc*/, char ** argv)
{
  // Initialize ImageMagick
  InitializeMagick(*argv);

  try {
    {
      // Read test image, just to have some pixels available    
      Image image("test.jpg");
      Blob blob;
      image.write( &blob );
      cout << "Size: " << image.columns() << 'x' <<image.rows() << " / JPEG Blob-Length: " << blob.length() << endl;

      // copy to global image.
      source=image;
      // Make source smaller, so the threads spend less time scaling and more time crashing.
      source.scale(Geometry(150,150));
    }
  } catch( Exception &error_ ) {
    cout << "Caught Exception: " << error_.what() << endl;
    return 1;
  } catch( exception &error_ ) {
    cout << "Caught exception: " << error_.what() << endl;
    return 1;
  }



  // Now start a bunch of threads.
  list<pthread_t> threads;

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  for (char i='A'; i<='Z'; ++i) {
    pthread_t thread;
    pthread_create(&thread,&attr,testthread,reinterpret_cast<void *>(static_cast<long>(i)));
    threads.push_back(thread);
  }

  // Wait for all threads to terminate.
  for (list<pthread_t>::iterator it=threads.begin(); it!=threads.end(); ++it) {
    void * result;
    pthread_join(*it,&result);
  }
  return 0;
}



