<commit_before>#include <string>
#include <vector>

#include "vtrc-server/vtrc-application.h"
#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "remote-fs-impl.h"
#include "protocol/remotefs.pb.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-unix-local.h"
#include "vtrc-server/vtrc-listener-win-pipe.h"

#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

class fs_application: public server::application {
    typedef fs_application this_type;
public:
    fs_application( common::pool_pair &pp )
        :server::application(pp)
    { }

    ~fs_application( )
    {
        google::protobuf::ShutdownProtobufLibrary( );
    }

    vtrc::shared_ptr<common::rpc_service_wrapper>
             get_service_by_name( common::connection_iface* connection,
                                  const std::string &service_name )
    {
        if( service_name == remote_fs::name( ) ) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_fs::create(connection));
        } else if(service_name == remote_file::name( )) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_file::create(connection));
        }
    }

    void on_new_connection( server::listener_sptr l,
                            const common::connection_iface *c )
    {
        std::cout << "New connection: "
                  << "\n\tep: "     << l->name( ) << "; "
                  << "\n\tclient: " << c->name( )
                  << "\n"
                    ;
    }

    void on_stop_connection( server::listener_sptr l,
                             const common::connection_iface *c )
    {
        std::cout << "Close connection: "
                  << c->name( ) << "\n";
    }

    void attach_listener( server::listener_sptr listen )
    {
        listen->get_on_new_connection( ).connect(
                    vtrc::bind( &this_type::on_new_connection, this,
                                listen, _1 ));
        listen->get_on_stop_connection( ).connect(
                    vtrc::bind( &this_type::on_stop_connection, this,
                                listen, _1 ));
    }

};

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::vector< std::string> >( ),
                     "endpoint name; <tcp address>:<port> or <pipe/file name>")

        ("io-pool-size,i",  po::value<unsigned>( ), "threads for io operations"
                                                    "; default = 1")
        ("rpc-pool-size,r", po::value<unsigned>( ), "threads for rpc calls"
                                                    "; default = 1")

        ;
}

server::listener_sptr create_from_string( const std::string &name,
                                          server::application &app)
{
    std::vector<std::string> params;
    boost::split( params, name, boost::is_any_of(":") );
    server::listener_sptr result;
    if( params.size( ) > 3 ) {
        std::ostringstream oss;
        oss << "Invalid endpoint name: " << name;
        throw std::runtime_error( oss.str( ) );
    }

    if( params.size( ) == 1 ) { // local name
#ifndef _WIN32
        ::unlink( params[0].c_str( ) );
        result = server::listeners::unix_local::create( app, params[0] );
#else
        result = server::listeners::win_pipe::create( app, params[0] );
#endif
    } else if( params.size( ) == 2 ) {
        result = server::listeners::tcp::create( app, params[0],
                boost::lexical_cast<unsigned short>(params[1]));
    }
    return result;
}

int start( const po::variables_map &params )
{
    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server endpoint is not defined;\n"
                                 "Use --help for details");
    }

    unsigned io_size = params.count( "io-pool-size" )
            ? params["io-pool-size"].as<unsigned>( )
            : 1;

    if( io_size < 1 ) {
        throw std::runtime_error( "io-pool-size must be at least 1" );
    }

    unsigned rpc_size = params.count( "rpc-pool-size" )
            ? params["rpc-pool-size"].as<unsigned>( )
            : 1;

    if( rpc_size < 1 ) {
        throw std::runtime_error( "rpc-pool-size must be at least 1" );
    }

    typedef std::vector<std::string> string_vector;
    string_vector servers = params["server"].as< string_vector >( );

    common::pool_pair pp( io_size, rpc_size );
    fs_application app( pp );

    std::vector<server::listener_sptr> listeners;

    listeners.reserve(servers.size( ));

    for( string_vector::const_iterator b(servers.begin( )), e(servers.end( ));
                    b != e; ++b)
    {
        std::cout << "Starting listener at '" <<  *b << "'\n";
        server::listener_sptr new_listener = create_from_string( *b, app );
        listeners.push_back(new_listener);
        app.attach_listener( new_listener );
        new_listener->start( );
    }

    pp.join_all( );

    return 0;
}
<commit_msg>examples; fix for tcpv6 address<commit_after>#include <string>
#include <vector>

#include "vtrc-server/vtrc-application.h"
#include "boost/program_options.hpp"
#include "boost/algorithm/string.hpp"

#include "vtrc-server/vtrc-application.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "remote-fs-impl.h"
#include "protocol/remotefs.pb.h"
#include "vtrc-common/vtrc-rpc-service-wrapper.h"

#include "vtrc-server/vtrc-listener-tcp.h"
#include "vtrc-server/vtrc-listener-unix-local.h"
#include "vtrc-server/vtrc-listener-win-pipe.h"

#include "vtrc-bind.h"
#include "vtrc-ref.h"

namespace po = boost::program_options;
using namespace vtrc;

class fs_application: public server::application {
    typedef fs_application this_type;
public:
    fs_application( common::pool_pair &pp )
        :server::application(pp)
    { }

    ~fs_application( )
    {
        google::protobuf::ShutdownProtobufLibrary( );
    }

    vtrc::shared_ptr<common::rpc_service_wrapper>
             get_service_by_name( common::connection_iface* connection,
                                  const std::string &service_name )
    {
        if( service_name == remote_fs::name( ) ) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_fs::create(connection));
        } else if(service_name == remote_file::name( )) {
            return vtrc::make_shared<common::rpc_service_wrapper>
                    (remote_file::create(connection));
        }
    }

    void on_new_connection( server::listener_sptr l,
                            const common::connection_iface *c )
    {
        std::cout << "New connection: "
                  << "\n\tep: "     << l->name( ) << "; "
                  << "\n\tclient: " << c->name( )
                  << "\n"
                    ;
    }

    void on_stop_connection( server::listener_sptr l,
                             const common::connection_iface *c )
    {
        std::cout << "Close connection: "
                  << c->name( ) << "\n";
    }

    void attach_listener( server::listener_sptr listen )
    {
        listen->get_on_new_connection( ).connect(
                    vtrc::bind( &this_type::on_new_connection, this,
                                listen, _1 ));
        listen->get_on_stop_connection( ).connect(
                    vtrc::bind( &this_type::on_stop_connection, this,
                                listen, _1 ));
    }

};

void get_options( po::options_description& desc )
{
    desc.add_options( )
        ("help,?",   "help message")
        ("server,s", po::value<std::vector< std::string> >( ),
                     "endpoint name; <tcp address>:<port> or <pipe/file name>")

        ("io-pool-size,i",  po::value<unsigned>( ), "threads for io operations"
                                                    "; default = 1")
        ("rpc-pool-size,r", po::value<unsigned>( ), "threads for rpc calls"
                                                    "; default = 1")

        ;
}

server::listener_sptr create_from_string( const std::string &name,
                                          server::application &app)
{

    server::listener_sptr result;

    std::vector<std::string> params;

    std::string::const_reverse_iterator b(name.rbegin( ));
    std::string::const_reverse_iterator e(name.rend( ));
    for( ; b!=e ;++b ) {
        if( *b == ':' ) {
            std::string::const_reverse_iterator bb(b);
            ++bb;
            params.push_back( std::string( name.begin( ), bb.base( )) );
            params.push_back( std::string( b.base( ), name.end( )));

            break;
        }
    }
    if( params.empty( ) ) {
        params.push_back( name );
    }

    if( params.size( ) == 1 ) { // local name
#ifndef _WIN32
        ::unlink( params[0].c_str( ) );
        result = server::listeners::unix_local::create( app, params[0] );
#else
        result = server::listeners::win_pipe::create( app, params[0] );
#endif
    } else if( params.size( ) == 2 ) {
        result = server::listeners::tcp::create( app, params[0],
                boost::lexical_cast<unsigned short>(params[1]));
    }
    return result;
}

int start( const po::variables_map &params )
{
    if( params.count( "server" ) == 0 ) {
        throw std::runtime_error("Server endpoint is not defined;\n"
                                 "Use --help for details");
    }

    unsigned io_size = params.count( "io-pool-size" )
            ? params["io-pool-size"].as<unsigned>( )
            : 1;

    if( io_size < 1 ) {
        throw std::runtime_error( "io-pool-size must be at least 1" );
    }

    unsigned rpc_size = params.count( "rpc-pool-size" )
            ? params["rpc-pool-size"].as<unsigned>( )
            : 1;

    if( rpc_size < 1 ) {
        throw std::runtime_error( "rpc-pool-size must be at least 1" );
    }

    typedef std::vector<std::string> string_vector;
    string_vector servers = params["server"].as< string_vector >( );

    common::pool_pair pp( io_size, rpc_size );
    fs_application app( pp );

    std::vector<server::listener_sptr> listeners;

    listeners.reserve(servers.size( ));

    for( string_vector::const_iterator b(servers.begin( )), e(servers.end( ));
                    b != e; ++b)
    {
        std::cout << "Starting listener at '" <<  *b << "'\n";
        server::listener_sptr new_listener = create_from_string( *b, app );
        listeners.push_back(new_listener);
        app.attach_listener( new_listener );
        new_listener->start( );
    }

    pp.join_all( );

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>[DF][NFC] Disable a test with jitted exceptions on windows<commit_after><|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <pthread.h>
//#include "carbon_user.h"     /* For the Graphite Simulator*/
#include <time.h>
#include <sys/timeb.h>

#define MAX            100000000
#define INT_MAX        100000000
// #define DEBUG              1
#define BILLION 1E9

int _W[8][8] =
{
   {0,   2,      1,      17,     MAX,    MAX,    MAX,    MAX},
   {2,   0,      MAX,    MAX,    2,      6,      MAX,    MAX},
   {1,   MAX,    0,      MAX,    MAX,    MAX,    MAX,    8},
   {17,  MAX,    MAX,    0,      MAX,    2,      1,      9},
   {MAX, 2,      MAX,    MAX,    0,      4,      MAX,    MAX},
   {MAX, 6,      MAX,    2,      4,      0,      5,      MAX},
   {MAX, MAX,    MAX,    1,      MAX,    5,      0,      3},
   {MAX, MAX,    8,      9,      MAX,    MAX,    3,      0}
};

int min = INT_MAX;
int min_index = 0;
pthread_mutex_t lock;
pthread_mutex_t locks[4194304];
int u = 0;

void init_weights(int N, int DEG, int** W, int** W_index)
{
   // Initialize to -1
   for(int i = 0; i < N; i++)
      for(int j = 0; j < DEG; j++)
         W_index[i][j]= -1;

   // Populate Index Array
   for(int i = 0; i < N; i++)
   {
      int last = 0;
      for(int j = 0; j < DEG; j++)
      {
         if(W_index[i][j] == -1)
         {
            int neighbor = i+j;
            //W_index[i][j] = i+j;//rand()%(DEG);

            if(neighbor > last)
            {
               W_index[i][j] = neighbor;
               last = W_index[i][j];
            }
            else
            {
               if(last < (N-1))
               {
                  W_index[i][j] = (last + 1);
                  last = W_index[i][j];
               }
            }
         }
         else
         {
            last = W_index[i][j];
         }
         if(W_index[i][j]>=N)
         {
            W_index[i][j] = N-1;
         }
      }
   }

   // Populate Cost Array
   for(int i = 0; i < N; i++)
   {
      for(int j = 0; j < DEG; j++)
      {
         double v = drand48();
         /*if(v > 0.8 || W_index[i][j] == -1)
           {       W[i][j] = MAX;
           W_index[i][j] = -1;
           }

           else*/ if(W_index[i][j] == i)
         W[i][j] = 0;

         else
            W[i][j] = (int) (v*100) + 1;
         //printf("   %d  ",W_index[i][j]);
      }
      //printf("\n");
   }
}

int initialize_single_source(int* D, int* Q, int source, int N);

typedef struct
{
   int*      local_min;
   int*      global_min;
   int*      Q;
   int*      D;
   //int**     W;
   int**     W_index;
   int*      d_count;
   int       tid;
   int       P;
   int       N;
   int       DEG;
   pthread_barrier_t* barrier_total;
   pthread_barrier_t* barrier;
} thread_arg_t;

int local_min_buffer[1024];
int Total_tid[1024] = {0};
int global_min_buffer;
int terminate = 0;
int range=1;
int old_range =1;
int difference=0;
int pid=0;
int P_global = 256;
int change = 0;
int *test;
int *test1;
int largest=0;
long long Total = 0;
thread_arg_t thread_arg[1024];
pthread_t   thread_handle[1024];

void* do_work(void* args)
{
   volatile thread_arg_t* arg = (thread_arg_t*) args;

   int tid                  = arg->tid;
   int P                    = arg->P;
   volatile int* Q          = arg->Q;
   int* D                   = arg->D;
   //int** W                  = arg->W;
   int** W_index            = arg->W_index;
   const int N              = arg->N;
   int uu = 0;

   int start =  0;  //tid    * DEG / (arg->P);
   int stop  = 0;   //(tid+1) * DEG / (arg->P);

   start =  tid    *  (largest) / (P);
   stop =  (tid+1) *  (largest) / (P);
   //printf("\n %d %d %d",tid,start,stop);

   pthread_barrier_wait(arg->barrier_total);

   for(uu=start;uu<stop;uu++)
   {
      if(test1[uu]==1)
      {
         for(int i = 0; i < test[uu]; i++)
         {
            int neighbor = W_index[uu][i];
            if(neighbor>=N)
               continue;

            pthread_mutex_lock(&locks[neighbor]);

            //if(uu>=N)
            //  terminate=1;

            D[W_index[uu][i]]++;
            Q[W_index[uu][i]] = 0;

            pthread_mutex_unlock(&locks[neighbor]);
         }
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   for(uu=start;uu<stop;uu++)
   {
      if(test1[uu]==1)
      {
         unsigned int ret = -1;
         /*while (D[uu] != 0)
           {
           D[uu] >>= 1;
           ret++;
           }*/
         ret = D[uu]/3;
         D[uu]=ret;
         if(D[uu]>=1)
         {
            //pthread_mutex_lock(&lock);
            Total_tid[tid] = Total_tid[tid]+D[uu];
            //pthread_mutex_unlock(&lock);
         }
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   if(tid==0)
   {
      for(int i=0;i<P;i++)
      {
         Total = Total + Total_tid[i];
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   return NULL;
}

int main(int argc, char** argv)
{
   //char filename[100];
   FILE *file0 = NULL;
   int N = 0;
   int DEG = 0;
   const int select = atoi(argv[1]);

   if(select==1)
   {
      const char *filename = argv[3];
      //printf("Please Enter The Name Of The File You Would Like To Fetch\n");
      //scanf("%s", filename);
      file0 = fopen(filename,"r");
   }

   int lines_to_check=0;
   char c;
   int number0;
   int number1;
   int inter = -1;

   if(select==1)
   {
      N = 2097152; //can be read from file if needed, this is a default upper limit
      DEG = 12;     //also can be reda from file if needed, upper limit here again
   }

   const int P1 = atoi(argv[2]);

   int P = P1;
   P_global = P1;
   //change = change1;
   old_range = change;
   range = change;

   if(select==0)
   {
      N = atoi(argv[3]);
      DEG = atoi(argv[4]);
      printf("\nGraph with Parameters: N:%d DEG:%d\n",N,DEG);
   }
   if (DEG > N)
   {
      fprintf(stderr, "Degree of graph cannot be grater than number of Vertices\n");
      exit(EXIT_FAILURE);
   }

   int* D;
   int* Q;
   if(posix_memalign((void**) &D, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &Q, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &test, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &test1, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   int d_count = N;
   pthread_barrier_t barrier_total;
   pthread_barrier_t barrier;

   int** W = (int**) malloc(N*sizeof(int*));
   int** W_index = (int**) malloc(N*sizeof(int*));
   for(int i = 0; i < N; i++)
   {
      //W[i] = (int *)malloc(sizeof(int)*N);
      if(posix_memalign((void**) &W[i], 64, DEG*sizeof(int)))
      {
         fprintf(stderr, "Allocation of memory failed\n");
         exit(EXIT_FAILURE);
      }
      if(posix_memalign((void**) &W_index[i], 64, DEG*sizeof(int)))
      {
         fprintf(stderr, "Allocation of memory failed\n");
         exit(EXIT_FAILURE);
      }
   }

   for(int i=0;i<N;i++)
   {
      for(int j=0;j<DEG;j++)
      {
         //W[i][j] = 1000000000;
         W_index[i][j] = INT_MAX;
      }
      test[i]=0;
      test1[i]=0;
   }

   if(select==1)
   {
      for(c=getc(file0); c!=EOF; c=getc(file0))
      {
         if(c=='\n')
            lines_to_check++;

         if(lines_to_check>3)
         {
            int f0 = fscanf(file0, "%d %d", &number0,&number1);
            if(f0 != 2 && f0 != EOF)
            {
               printf ("Error: Read %d values, expected 2. Parsing failed.\n",f0);
               exit (EXIT_FAILURE);
            }
            //printf("\n%d %d",number0,number1);
            if(number0>largest)
               largest=number0;
            if(number1>largest)
               largest=number1;
            inter = test[number0];

            //W[number0][inter] = drand48();
            W_index[number0][inter] = number1;
            //previous_node = number0;
            test[number0]++;
            test1[number0]=1; test1[number1]=1;
         }
      }
      printf("\nFile Read, Largest Vertex:%d",largest);
   }

   if(select==0)
   {
      init_weights(N, DEG, W, W_index);
      largest = N;
   }
   /*for(int i = 0;i<100;i++)
     {
     for(int j = 0;j<4;j++)
     {
     printf(" %d ",W_index[i][j]);
     }
     printf("\n");
     }*/

   pthread_barrier_init(&barrier_total, NULL, P);
   pthread_barrier_init(&barrier, NULL, P);

   pthread_mutex_init(&lock, NULL);

   for(int i=0; i<largest; i++)
   {
      if(select==0)
      {
         test1[i]=1;
         test[i]=DEG;
      }
      if(test1[i]==1)
         pthread_mutex_init(&locks[i], NULL);
   }

   initialize_single_source(D, Q, 0, N);

   for(int j = 0; j < P; j++) {
      thread_arg[j].local_min  = local_min_buffer;
      thread_arg[j].global_min = &global_min_buffer;
      thread_arg[j].Q          = Q;
      thread_arg[j].D          = D;
      //thread_arg[j].W          = W;
      thread_arg[j].W_index    = W_index;
      thread_arg[j].d_count    = &d_count;
      thread_arg[j].tid        = j;
      thread_arg[j].P          = P;
      thread_arg[j].N          = N;
      thread_arg[j].DEG        = DEG;
      thread_arg[j].barrier_total = &barrier_total;
      thread_arg[j].barrier    = &barrier;
   }

   struct timespec requestStart, requestEnd;
   clock_gettime(CLOCK_REALTIME, &requestStart);

   // Enable Graphite performance and energy models
   //CarbonEnableModels();

   for(int j = 1; j < P; j++) {
      pthread_create(thread_handle+j,
            NULL,
            do_work,
            (void*)&thread_arg[j]);
   }
   do_work((void*) &thread_arg[0]);

   for(int j = 1; j < P; j++) { //mul = mul*2;
      pthread_join(thread_handle[j],NULL);
   }

   // Disable Graphite performance and energy models
   //CarbonDisableModels();

   printf("\nThreads Joined!");

   clock_gettime(CLOCK_REALTIME, &requestEnd);
   double accum = ( requestEnd.tv_sec - requestStart.tv_sec ) + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / BILLION;
   printf( "\nTime Taken:\n%lf seconds", accum );

   printf("\nTriangles=%lld \n",Total);

   return 0;
}

int initialize_single_source(int*  D,
      int*  Q,
      int   source,
      int   N)
{
   for(int i = 0; i < N+1; i++)
   {
      D[i] = 0;
      Q[i] = 1;
   }

   //D[source] = 0;
   return 0;
}
<commit_msg>cleaned up triangle counting<commit_after>#include <cstdio>
#include <cstdlib>
#include <pthread.h>
//#include "carbon_user.h"     /* For the Graphite Simulator*/
#include <time.h>
#include <sys/timeb.h>

#define MAX            100000000
#define INT_MAX        100000000
#define BILLION 1E9

//Thread Argument Structure
typedef struct
{
   int*      local_min;
   int*      global_min;
   int*      Q;
   int*      D;
   //int**     W;
   int**     W_index;
   int*      d_count;
   int       tid;
   int       P;
   int       N;
   int       DEG;
   pthread_barrier_t* barrier_total;
   pthread_barrier_t* barrier;
} thread_arg_t;

//Function Declarations
int initialize_single_source(int* D, int* Q, int source, int N);
void init_weights(int N, int DEG, int** W, int** W_index);

//Global Variables
pthread_mutex_t lock;
pthread_mutex_t locks[4194304];      //Lock for each vertex
int local_min_buffer[1024];
int Total_tid[1024] = {0};           //To store triangles per thread
int global_min_buffer;
int P_global = 256;
int *edges;
int *exist;
int largest=0;
long long Total_Tri = 0;                 //Stores total triangles
thread_arg_t thread_arg[1024];       //Max threads and pthread handlers
pthread_t   thread_handle[1024];

//Primary Parallel Function
void* do_work(void* args)
{
   //Thread Variables
   volatile thread_arg_t* arg = (thread_arg_t*) args;
   int tid                  = arg->tid;
   int P                    = arg->P;
   volatile int* Q          = arg->Q;
   int* D                   = arg->D;         //stores edges
   //int** W                = arg->W;
   int** W_index            = arg->W_index;   //Graph connections
   const int N              = arg->N;
   int v                    = 0;              //for each vertex

   int start =  0;  //tid    * DEG / (arg->P);
   int stop  = 0;   //(tid+1) * DEG / (arg->P);

   //Chunk work into threads
   start =  tid    *  (largest) / (P);
   stop =  (tid+1) *  (largest) / (P);
   //printf("\n %d %d %d",tid,start,stop);

   pthread_barrier_wait(arg->barrier_total);

   //Look at all edges
   for(v=start;v<stop;v++)
   {
      if(exist[v]==1)
      {
         for(int i = 0; i < edges[v]; i++)
         {
            int neighbor = W_index[v][i];
            if(neighbor>=N)
               continue;

            pthread_mutex_lock(&locks[neighbor]);

            D[W_index[v][i]]++;   //Add edges
            Q[W_index[v][i]] = 0;

            pthread_mutex_unlock(&locks[neighbor]);
         }
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   //Find triangles for each thread
   for(v=start;v<stop;v++)
   {
      if(exist[v]==1)
      {
         unsigned int ret = -1;
         /*while (D[uu] != 0)
           {
           D[uu] >>= 1;
           ret++;
           }*/
         ret = D[v]/3;
         D[v]=ret;
         if(D[v]>=1)
         {
            //pthread_mutex_lock(&lock);
            Total_tid[tid] = Total_tid[tid]+D[v];
            //pthread_mutex_unlock(&lock);
         }
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   //The master thread sums up all triangles
   if(tid==0)
   {
      for(int i=0;i<P;i++)
      {
         Total_Tri = Total_Tri + Total_tid[i];
      }
   }

   pthread_barrier_wait(arg->barrier_total);

   return NULL;
}

int main(int argc, char** argv)
{
   //char filename[100];
   FILE *file0 = NULL;
   int N = 0;
   int DEG = 0;
   const int select = atoi(argv[1]);

   //For reading graph from file
   if(select==1)
   {
      const char *filename = argv[3];
      //printf("Please Enter The Name Of The File You Would Like To Fetch\n");
      //scanf("%s", filename);
      file0 = fopen(filename,"r");
   }

   int lines_to_check=0;
   char c;
   int number0;
   int number1;
   int inter = -1;

   if(select==1)
   {
      N = 2097152; //can be read from file if needed, this is a default upper limit
      DEG = 12;     //also can be reda from file if needed, upper limit here again
   }

   const int P1 = atoi(argv[2]);

   int P = P1;
   P_global = P1;

   if(select==0)
   {
      N = atoi(argv[3]);
      DEG = atoi(argv[4]);
      printf("\nGraph with Parameters: N:%d DEG:%d\n",N,DEG);
   }
   if (DEG > N)
   {
      fprintf(stderr, "Degree of graph cannot be grater than number of Vertices\n");
      exit(EXIT_FAILURE);
   }

   //Memory Allocations
   int* D;
   int* Q;
   if(posix_memalign((void**) &D, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &Q, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &edges, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   if(posix_memalign((void**) &exist, 64, N * sizeof(int)))
   {
      fprintf(stderr, "Allocation of memory failed\n");
      exit(EXIT_FAILURE);
   }
   int d_count = N;
   pthread_barrier_t barrier_total;
   pthread_barrier_t barrier;

   int** W = (int**) malloc(N*sizeof(int*));
   int** W_index = (int**) malloc(N*sizeof(int*));
   for(int i = 0; i < N; i++)
   {
      //W[i] = (int *)malloc(sizeof(int)*N);
      if(posix_memalign((void**) &W[i], 64, DEG*sizeof(int)))
      {
         fprintf(stderr, "Allocation of memory failed\n");
         exit(EXIT_FAILURE);
      }
      if(posix_memalign((void**) &W_index[i], 64, DEG*sizeof(int)))
      {
         fprintf(stderr, "Allocation of memory failed\n");
         exit(EXIT_FAILURE);
      }
   }

   for(int i=0;i<N;i++)
   {
      for(int j=0;j<DEG;j++)
      {
         //W[i][j] = 1000000000;
         W_index[i][j] = INT_MAX;
      }
      edges[i]=0;
      exist[i]=0;
   }

   //For real graphs
   if(select==1)
   {
      for(c=getc(file0); c!=EOF; c=getc(file0))
      {
         if(c=='\n')
            lines_to_check++;

         if(lines_to_check>3)
         {
            int f0 = fscanf(file0, "%d %d", &number0,&number1);
            if(f0 != 2 && f0 != EOF)
            {
               printf ("Error: Read %d values, expected 2. Parsing failed.\n",f0);
               exit (EXIT_FAILURE);
            }
            //printf("\n%d %d",number0,number1);
            if(number0>largest)
               largest=number0;
            if(number1>largest)
               largest=number1;
            inter = edges[number0];

            //W[number0][inter] = drand48();
            W_index[number0][inter] = number1;
            //previous_node = number0;
            edges[number0]++;
            exist[number0]=1; exist[number1]=1;
         }
      }
      printf("\nFile Read, Largest Vertex:%d",largest);
   }

   //For synthetic graphs
   if(select==0)
   {
      init_weights(N, DEG, W, W_index);
      largest = N;
   }

   //Initialize Synchronization Variables
   pthread_barrier_init(&barrier_total, NULL, P);
   pthread_barrier_init(&barrier, NULL, P);
   pthread_mutex_init(&lock, NULL);

   for(int i=0; i<largest+1; i++)
   {
      if(select==0)
      {
         exist[i]=1;
         edges[i]=DEG;
      }
      if(exist[i]==1)
         pthread_mutex_init(&locks[i], NULL);
   }

   //Initialize 1-d arrays
   initialize_single_source(D, Q, 0, N);

   //Thread Arguments
   for(int j = 0; j < P; j++) {
      thread_arg[j].local_min  = local_min_buffer;
      thread_arg[j].global_min = &global_min_buffer;
      thread_arg[j].Q          = Q;
      thread_arg[j].D          = D;
      //thread_arg[j].W          = W;
      thread_arg[j].W_index    = W_index;
      thread_arg[j].d_count    = &d_count;
      thread_arg[j].tid        = j;
      thread_arg[j].P          = P;
      thread_arg[j].N          = N;
      thread_arg[j].DEG        = DEG;
      thread_arg[j].barrier_total = &barrier_total;
      thread_arg[j].barrier    = &barrier;
   }

   struct timespec requestStart, requestEnd;
   clock_gettime(CLOCK_REALTIME, &requestStart);

   // Enable Graphite performance and energy models
   //CarbonEnableModels();

   //Start Threads
   for(int j = 1; j < P; j++) {
      pthread_create(thread_handle+j,
            NULL,
            do_work,
            (void*)&thread_arg[j]);
   }
   do_work((void*) &thread_arg[0]);

   //Join Threads
   for(int j = 1; j < P; j++) { //mul = mul*2;
      pthread_join(thread_handle[j],NULL);
   }

   // Disable Graphite performance and energy models
   //CarbonDisableModels();

   printf("\nThreads Joined!");

   //Print Time Taken
   clock_gettime(CLOCK_REALTIME, &requestEnd);
   double accum = ( requestEnd.tv_sec - requestStart.tv_sec ) + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / BILLION;
   printf( "\nTime Taken:\n%lf seconds", accum );

   printf("\nTriangles=%lld \n",Total_Tri);

   return 0;
}

int initialize_single_source(int*  D,
      int*  Q,
      int   source,
      int   N)
{
   for(int i = 0; i < N+1; i++)
   {
      D[i] = 0;
      Q[i] = 1;
   }

   //D[source] = 0;
   return 0;
}

//Graph Generator
void init_weights(int N, int DEG, int** W, int** W_index)
{
   // Initialize to -1
   for(int i = 0; i < N; i++)
      for(int j = 0; j < DEG; j++)
         W_index[i][j]= -1;

   // Populate Index Array
   for(int i = 0; i < N; i++)
   {
      int last = 0;
      for(int j = 0; j < DEG; j++)
      {
         if(W_index[i][j] == -1)
         {
            int neighbor = i+j;
            //W_index[i][j] = i+j;//rand()%(DEG);

            if(neighbor > last)
            {
               W_index[i][j] = neighbor;
               last = W_index[i][j];
            }
            else
            {
               if(last < (N-1))
               {
                  W_index[i][j] = (last + 1);
                  last = W_index[i][j];
               }
            }
         }
         else
         {
            last = W_index[i][j];
         }
         if(W_index[i][j]>=N)
         {
            W_index[i][j] = N-1;
         }
      }
   }

   // Populate Cost Array
   for(int i = 0; i < N; i++)
   {
      for(int j = 0; j < DEG; j++)
      {
         double v = drand48();
         /*if(v > 0.8 || W_index[i][j] == -1)
           {       W[i][j] = MAX;
           W_index[i][j] = -1;
           }

           else*/ if(W_index[i][j] == i)
         W[i][j] = 0;

         else
            W[i][j] = (int) (v*100) + 1;
         //printf("   %d  ",W_index[i][j]);
      }
      //printf("\n");
   }
}
<|endoftext|>


<commit_before>#ifndef ENGINE_COMPONENT_APP_OVERSEER_REAL_HPP
#define ENGINE_COMPONENT_APP_OVERSEER_REAL_HPP
#pragma once

#include "global/component/app_overseer.hpp"
#include "global/core/messenger.hpp"
#include "global/component/logger.hpp"
#include "global/core/process/service.hpp"
#include "utility/container/concurrent_queue.hpp"
#include "utility/concurrention/signal.hpp"

namespace engine
{

	class app_overseer_actual_t
	{

	public:

		app_overseer_actual_t(std::shared_ptr<logger_t> logger) : logger(logger)
		{

		}

		void run_app(app_t::kind_t kind, std::unique_ptr<app_context_t> context, app_overseer_t::run_app_instance_t instance = app_overseer_t::run_app_instance_t::allow_multiple, app_overseer_t::run_app_other_t other = app_overseer_t::run_app_other_t::keep, app_overseer_t::callback_app_t app_running = [](std::shared_ptr<app_t>){}, app_overseer_t::callback_void_t run_failed = [](){})
		{
			events.push(std::make_unique<run_app_event_t>(kind, std::move(context), instance, other, std::move(app_running), std::move(run_failed)));
		}

        void terminate_app(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_completed = [](){})
		{
			events.push(std::make_unique<terminate_app_event_t>(instance, std::move(on_completed)));
		}

        void close_app(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_accepted = [](){}, app_overseer_t::callback_void_t on_rejected = [](){})
		{
			events.push(std::make_unique<close_app_event_t>(instance, std::move(on_accepted), std::move(on_rejected)));
		}

        void wait_for_completion()
		{
			check_for_completion();
			signal_completion.wait();
		}

		void app_created(std::shared_ptr<app_meta_t> app_meta)
		{
			events.push(std::make_unique<app_created_event_t>(app_meta));
		}

		void app_destroyed(std::shared_ptr<app_meta_t> app_meta)
		{
			events.push(std::make_unique<app_destroyed_event_t>(app_meta));
		}

        void terminate()
		{
			events.push(std::unique_ptr<event_t>());
		}

		task_base_t::result_t run()
		{
			for(;;)
			{
				std::unique_ptr<event_t> event = std::move(events.pop());
				if(!event) return task_base_t::result_t::completed;
				handle_event(std::move(event));
			}
		}

	private:

		signal_t signal_completion;

		class event_t
		{
			public:

				virtual ~event_t()
				{

				}

				enum class type_t
				{
					run_app,
					terminate_app,
					close_app,
					app_created,
					app_destroyed
				};

				type_t get_type() const
				{
					return type;
				}

			protected:

				event_t(type_t type) : type(type)
				{

				}

			private:

				type_t type;
		};

		concurrent_queue_t<std::unique_ptr<event_t> > events;

		class run_app_event_t : public event_t
		{

			public:

				run_app_event_t(app_t::kind_t kind, std::unique_ptr<app_context_t> context, app_overseer_t::run_app_instance_t instance = app_overseer_t::run_app_instance_t::allow_multiple, app_overseer_t::run_app_other_t other = app_overseer_t::run_app_other_t::keep, app_overseer_t::callback_app_t app_running = [](std::shared_ptr<app_t>){}, app_overseer_t::callback_void_t run_failed = [](){}) :
					event_t(type_t::run_app), kind(kind), context(std::move(context)), instance(instance), other(other), app_running(std::move(app_running)), run_failed(std::move(run_failed))
				{

				}

				app_t::kind_t get_kind() const
				{
					return  kind;
				}

				app_context_t * get_context() const
				{
					return context.get();
				}

				std::unique_ptr<app_context_t> move_context()
				{
					return std::move(context);
				}

				app_overseer_t::run_app_instance_t get_instance() const
				{
					return instance;
				}

				app_overseer_t::run_app_other_t get_other() const
				{
					return other;
				}

				void execute_callback_app_running(std::shared_ptr<app_t> app)
				{
					app_running(app);
				}

				void execute_callback_run_failed()
				{
					run_failed();
				}

			private:

				app_t::kind_t kind;
				std::unique_ptr<app_context_t> context;
				app_overseer_t::run_app_instance_t instance;
				app_overseer_t::run_app_other_t other;
				app_overseer_t::callback_app_t app_running;
				app_overseer_t::callback_void_t run_failed;

		};

		class terminate_app_event_t : public event_t
		{

			public:

				terminate_app_event_t(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_completed = [](){}) : event_t(type_t::terminate_app), instance(instance), on_completed(std::move(on_completed))
				{

				}

				app_t::instance_id_t get_instance() const
				{
					return instance;
				}

				void execute_callback_on_completed()
				{
					on_completed();
				}

			private:

				app_t::instance_id_t instance;
				app_overseer_t::callback_void_t on_completed;
		};

		class close_app_event_t : public event_t
		{

			public:

				close_app_event_t(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_accepted = [](){}, app_overseer_t::callback_void_t on_rejected = [](){}) : event_t(type_t::close_app), instance(instance), on_accepted(std::move(on_accepted)), on_rejected(std::move(on_rejected))
				{

				}

				app_t::instance_id_t get_instance() const
				{
					return instance;
				}

				void execute_callback_on_accepted()
				{
					on_accepted();
				}

				void execute_callback_on_rejected()
				{
					on_rejected();
				}

			private:

				app_t::instance_id_t instance;
				app_overseer_t::callback_void_t on_accepted;
				app_overseer_t::callback_void_t on_rejected;
		};

		class app_created_event_t : public event_t
		{

			public:

				app_created_event_t(std::shared_ptr<app_meta_t> meta) : event_t(type_t::app_created), meta(meta)
				{

				}

				std::shared_ptr<app_meta_t> get_meta()
				{
					return meta;
				}

			private:

				std::shared_ptr<app_meta_t> meta;
		};

		class app_destroyed_event_t : public event_t
		{

			public:

				app_destroyed_event_t(std::shared_ptr<app_meta_t> meta) : event_t(type_t::app_destroyed), meta(meta)
				{

				}

				std::shared_ptr<app_meta_t> get_meta()
				{
					return meta;
				}

			private:

				std::shared_ptr<app_meta_t> meta;
		};

		std::shared_ptr<logger_t> logger;
		std::vector<std::shared_ptr<app_meta_t> > apps_meta;

		enum class flag_t
		{
			is_done,
			count
		};

		flags_t<flag_t> flags;

		void check_for_completion()
		{
			if(apps_meta.empty() && events.is_empty())
			{
				flags.set_flag(flag_t::is_done, true);
				signal_completion.signal();
			}
		}

		void handle_app_created_event(app_created_event_t * event)
		{
			auto iter = std::find(apps_meta.begin(), apps_meta.end(), event->get_meta());
			if(iter == apps_meta.end())
				apps_meta.push_back(event->get_meta());
		}

		void handle_app_destroyed_event(app_destroyed_event_t * event)
		{
			auto iter = std::find(apps_meta.begin(), apps_meta.end(), event->get_meta());
			if(iter != apps_meta.end())
				apps_meta.erase(iter);
		}

		void handle_event(std::unique_ptr<event_t> event)
		{
			if(!flags.is_flag(flag_t::is_done))
			{
				switch(event->get_type())
				{
					case event_t::type_t::app_created:
						handle_app_created_event(static_cast<app_created_event_t*>(event.get()));
					break;
					case event_t::type_t::app_destroyed:
						handle_app_destroyed_event(static_cast<app_destroyed_event_tc*>(event.get()));
					break;
				}
				check_for_completion();
			}
		}

	};

	class app_overseer_service_t : public service_base_t
	{

	public:

		app_overseer_service_t(std::shared_ptr<logger_t> logger, std::shared_ptr<app_overseer_actual_t> actual) : logger(logger), actual(actual)
		{
			logger->log_global_msg(apps, "App overseer service has started"_u);
		}

		~app_overseer_service_t()
		{
			logger->log_global_msg(apps, "App overseer service has concluded"_u);
		}

		ustring_t get_name() const final
		{
			return "App overseer service"_u;
		}

		task_base_t::result_t run() final
		{
			return actual->run();
		}

		void on_end_requested() final
		{
			actual->terminate();
		}

	private:

		std::shared_ptr<logger_t> logger;
		std::shared_ptr<app_overseer_actual_t> actual;

	};

	class app_overseer_real_t : public app_overseer_t
	{

	public:

		app_overseer_real_t(std::shared_ptr<logger_t> logger, std::unique_ptr<service_t<app_overseer_service_t>> service, std::shared_ptr<messenger_accountable_app_t> messenger_accountable_app, std::shared_ptr<app_overseer_actual_t> actual) : logger(logger), service(std::move(service)), messenger_accountable_app(messenger_accountable_app)
		{
			auto task_id = logger->log_global_task_start(apps, "Initializing overseer [app]"_u);
			messenger_instance = messenger_accountable_app->register_callback([this](messenger::msg_accountable_app_t* msg){on_accountable_changed(msg);}, messenger::history_t::dump_if_available);
			this->service->start();
			logger->log_global_task_done(task_id);
		}

		~app_overseer_real_t()
		{
			auto task_id = logger->log_global_task_start(apps, "App overseer is being disposed"_u);
			this->service->end();
			logger->log_global_task_done(task_id);
		}

		void run_app(app_t::kind_t kind, std::unique_ptr<app_context_t> context, run_app_instance_t instance = run_app_instance_t::allow_multiple, run_app_other_t other = run_app_other_t::keep, callback_app_t app_running = [](std::shared_ptr<app_t>){}, callback_void_t run_failed = [](){}) final
		{
			actual->run_app(kind, std::move(context), instance, other, std::move(app_running), std::move(run_failed));
		}
        void terminate_app(app_t::instance_id_t instance, callback_void_t on_completed = [](){}) final
		{
			actual->terminate_app(instance, std::move(on_completed));
		}
        void close_app(app_t::instance_id_t instance, callback_void_t on_accepted = [](){}, callback_void_t on_rejected = [](){}) final
		{
			actual->close_app(instance, std::move(on_accepted), std::move(on_rejected));
		}
        void wait_for_completion() final
		{
			actual->wait_for_completion();
		}

	private:

		std::shared_ptr<logger_t> logger;
		std::unique_ptr<service_t<app_overseer_service_t>> service;
		std::shared_ptr<messenger_accountable_app_t> messenger_accountable_app;
 		std::shared_ptr<app_overseer_actual_t> actual;

		void on_accountable_created(messenger::msg_accountable_app_t * msg)
		{
			actual->app_created(msg->get_object()->get_meta());
		}

        void on_accountable_destroyed(messenger::msg_accountable_app_t * msg)
		{
			actual->app_destroyed(msg->get_object()->get_meta());
		}

		void on_accountable_changed(messenger::msg_accountable_app_t* msg)
		{
			switch(msg->get_type())
			{
				case messenger::accountable_type_t::create:
                    on_accountable_created(msg);
				break;
				case messenger::accountable_type_t::destroy:
                    on_accountable_destroyed(msg);
				break;
			}
		}

		std::unique_ptr<messenger::instance_t<messenger::msg_accountable_app_t> > messenger_instance;

	};
}

#endif<commit_msg>Fixed leftover typo from previous commit<commit_after>#ifndef ENGINE_COMPONENT_APP_OVERSEER_REAL_HPP
#define ENGINE_COMPONENT_APP_OVERSEER_REAL_HPP
#pragma once

#include "global/component/app_overseer.hpp"
#include "global/core/messenger.hpp"
#include "global/component/logger.hpp"
#include "global/core/process/service.hpp"
#include "utility/container/concurrent_queue.hpp"
#include "utility/concurrention/signal.hpp"

namespace engine
{

	class app_overseer_actual_t
	{

	public:

		app_overseer_actual_t(std::shared_ptr<logger_t> logger) : logger(logger)
		{

		}

		void run_app(app_t::kind_t kind, std::unique_ptr<app_context_t> context, app_overseer_t::run_app_instance_t instance = app_overseer_t::run_app_instance_t::allow_multiple, app_overseer_t::run_app_other_t other = app_overseer_t::run_app_other_t::keep, app_overseer_t::callback_app_t app_running = [](std::shared_ptr<app_t>){}, app_overseer_t::callback_void_t run_failed = [](){})
		{
			events.push(std::make_unique<run_app_event_t>(kind, std::move(context), instance, other, std::move(app_running), std::move(run_failed)));
		}

        void terminate_app(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_completed = [](){})
		{
			events.push(std::make_unique<terminate_app_event_t>(instance, std::move(on_completed)));
		}

        void close_app(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_accepted = [](){}, app_overseer_t::callback_void_t on_rejected = [](){})
		{
			events.push(std::make_unique<close_app_event_t>(instance, std::move(on_accepted), std::move(on_rejected)));
		}

        void wait_for_completion()
		{
			check_for_completion();
			signal_completion.wait();
		}

		void app_created(std::shared_ptr<app_meta_t> app_meta)
		{
			events.push(std::make_unique<app_created_event_t>(app_meta));
		}

		void app_destroyed(std::shared_ptr<app_meta_t> app_meta)
		{
			events.push(std::make_unique<app_destroyed_event_t>(app_meta));
		}

        void terminate()
		{
			events.push(std::unique_ptr<event_t>());
		}

		task_base_t::result_t run()
		{
			for(;;)
			{
				std::unique_ptr<event_t> event = std::move(events.pop());
				if(!event) return task_base_t::result_t::completed;
				handle_event(std::move(event));
			}
		}

	private:

		signal_t signal_completion;

		class event_t
		{
			public:

				virtual ~event_t()
				{

				}

				enum class type_t
				{
					run_app,
					terminate_app,
					close_app,
					app_created,
					app_destroyed
				};

				type_t get_type() const
				{
					return type;
				}

			protected:

				event_t(type_t type) : type(type)
				{

				}

			private:

				type_t type;
		};

		concurrent_queue_t<std::unique_ptr<event_t> > events;

		class run_app_event_t : public event_t
		{

			public:

				run_app_event_t(app_t::kind_t kind, std::unique_ptr<app_context_t> context, app_overseer_t::run_app_instance_t instance = app_overseer_t::run_app_instance_t::allow_multiple, app_overseer_t::run_app_other_t other = app_overseer_t::run_app_other_t::keep, app_overseer_t::callback_app_t app_running = [](std::shared_ptr<app_t>){}, app_overseer_t::callback_void_t run_failed = [](){}) :
					event_t(type_t::run_app), kind(kind), context(std::move(context)), instance(instance), other(other), app_running(std::move(app_running)), run_failed(std::move(run_failed))
				{

				}

				app_t::kind_t get_kind() const
				{
					return  kind;
				}

				app_context_t * get_context() const
				{
					return context.get();
				}

				std::unique_ptr<app_context_t> move_context()
				{
					return std::move(context);
				}

				app_overseer_t::run_app_instance_t get_instance() const
				{
					return instance;
				}

				app_overseer_t::run_app_other_t get_other() const
				{
					return other;
				}

				void execute_callback_app_running(std::shared_ptr<app_t> app)
				{
					app_running(app);
				}

				void execute_callback_run_failed()
				{
					run_failed();
				}

			private:

				app_t::kind_t kind;
				std::unique_ptr<app_context_t> context;
				app_overseer_t::run_app_instance_t instance;
				app_overseer_t::run_app_other_t other;
				app_overseer_t::callback_app_t app_running;
				app_overseer_t::callback_void_t run_failed;

		};

		class terminate_app_event_t : public event_t
		{

			public:

				terminate_app_event_t(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_completed = [](){}) : event_t(type_t::terminate_app), instance(instance), on_completed(std::move(on_completed))
				{

				}

				app_t::instance_id_t get_instance() const
				{
					return instance;
				}

				void execute_callback_on_completed()
				{
					on_completed();
				}

			private:

				app_t::instance_id_t instance;
				app_overseer_t::callback_void_t on_completed;
		};

		class close_app_event_t : public event_t
		{

			public:

				close_app_event_t(app_t::instance_id_t instance, app_overseer_t::callback_void_t on_accepted = [](){}, app_overseer_t::callback_void_t on_rejected = [](){}) : event_t(type_t::close_app), instance(instance), on_accepted(std::move(on_accepted)), on_rejected(std::move(on_rejected))
				{

				}

				app_t::instance_id_t get_instance() const
				{
					return instance;
				}

				void execute_callback_on_accepted()
				{
					on_accepted();
				}

				void execute_callback_on_rejected()
				{
					on_rejected();
				}

			private:

				app_t::instance_id_t instance;
				app_overseer_t::callback_void_t on_accepted;
				app_overseer_t::callback_void_t on_rejected;
		};

		class app_created_event_t : public event_t
		{

			public:

				app_created_event_t(std::shared_ptr<app_meta_t> meta) : event_t(type_t::app_created), meta(meta)
				{

				}

				std::shared_ptr<app_meta_t> get_meta()
				{
					return meta;
				}

			private:

				std::shared_ptr<app_meta_t> meta;
		};

		class app_destroyed_event_t : public event_t
		{

			public:

				app_destroyed_event_t(std::shared_ptr<app_meta_t> meta) : event_t(type_t::app_destroyed), meta(meta)
				{

				}

				std::shared_ptr<app_meta_t> get_meta()
				{
					return meta;
				}

			private:

				std::shared_ptr<app_meta_t> meta;
		};

		std::shared_ptr<logger_t> logger;
		std::vector<std::shared_ptr<app_meta_t> > apps_meta;

		enum class flag_t
		{
			is_done,
			count
		};

		flags_t<flag_t> flags;

		void check_for_completion()
		{
			if(apps_meta.empty() && events.is_empty())
			{
				flags.set_flag(flag_t::is_done, true);
				signal_completion.signal();
			}
		}

		void handle_app_created_event(app_created_event_t * event)
		{
			auto iter = std::find(apps_meta.begin(), apps_meta.end(), event->get_meta());
			if(iter == apps_meta.end())
				apps_meta.push_back(event->get_meta());
		}

		void handle_app_destroyed_event(app_destroyed_event_t * event)
		{
			auto iter = std::find(apps_meta.begin(), apps_meta.end(), event->get_meta());
			if(iter != apps_meta.end())
				apps_meta.erase(iter);
		}

		void handle_event(std::unique_ptr<event_t> event)
		{
			if(!flags.is_flag(flag_t::is_done))
			{
				switch(event->get_type())
				{
					case event_t::type_t::app_created:
						handle_app_created_event(static_cast<app_created_event_t*>(event.get()));
					break;
					case event_t::type_t::app_destroyed:
						handle_app_destroyed_event(static_cast<app_destroyed_event_t*>(event.get()));
					break;
				}
				check_for_completion();
			}
		}

	};

	class app_overseer_service_t : public service_base_t
	{

	public:

		app_overseer_service_t(std::shared_ptr<logger_t> logger, std::shared_ptr<app_overseer_actual_t> actual) : logger(logger), actual(actual)
		{
			logger->log_global_msg(apps, "App overseer service has started"_u);
		}

		~app_overseer_service_t()
		{
			logger->log_global_msg(apps, "App overseer service has concluded"_u);
		}

		ustring_t get_name() const final
		{
			return "App overseer service"_u;
		}

		task_base_t::result_t run() final
		{
			return actual->run();
		}

		void on_end_requested() final
		{
			actual->terminate();
		}

	private:

		std::shared_ptr<logger_t> logger;
		std::shared_ptr<app_overseer_actual_t> actual;

	};

	class app_overseer_real_t : public app_overseer_t
	{

	public:

		app_overseer_real_t(std::shared_ptr<logger_t> logger, std::unique_ptr<service_t<app_overseer_service_t>> service, std::shared_ptr<messenger_accountable_app_t> messenger_accountable_app, std::shared_ptr<app_overseer_actual_t> actual) : logger(logger), service(std::move(service)), messenger_accountable_app(messenger_accountable_app)
		{
			auto task_id = logger->log_global_task_start(apps, "Initializing overseer [app]"_u);
			messenger_instance = messenger_accountable_app->register_callback([this](messenger::msg_accountable_app_t* msg){on_accountable_changed(msg);}, messenger::history_t::dump_if_available);
			this->service->start();
			logger->log_global_task_done(task_id);
		}

		~app_overseer_real_t()
		{
			auto task_id = logger->log_global_task_start(apps, "App overseer is being disposed"_u);
			this->service->end();
			logger->log_global_task_done(task_id);
		}

		void run_app(app_t::kind_t kind, std::unique_ptr<app_context_t> context, run_app_instance_t instance = run_app_instance_t::allow_multiple, run_app_other_t other = run_app_other_t::keep, callback_app_t app_running = [](std::shared_ptr<app_t>){}, callback_void_t run_failed = [](){}) final
		{
			actual->run_app(kind, std::move(context), instance, other, std::move(app_running), std::move(run_failed));
		}
        void terminate_app(app_t::instance_id_t instance, callback_void_t on_completed = [](){}) final
		{
			actual->terminate_app(instance, std::move(on_completed));
		}
        void close_app(app_t::instance_id_t instance, callback_void_t on_accepted = [](){}, callback_void_t on_rejected = [](){}) final
		{
			actual->close_app(instance, std::move(on_accepted), std::move(on_rejected));
		}
        void wait_for_completion() final
		{
			actual->wait_for_completion();
		}

	private:

		std::shared_ptr<logger_t> logger;
		std::unique_ptr<service_t<app_overseer_service_t>> service;
		std::shared_ptr<messenger_accountable_app_t> messenger_accountable_app;
 		std::shared_ptr<app_overseer_actual_t> actual;

		void on_accountable_created(messenger::msg_accountable_app_t * msg)
		{
			actual->app_created(msg->get_object()->get_meta());
		}

        void on_accountable_destroyed(messenger::msg_accountable_app_t * msg)
		{
			actual->app_destroyed(msg->get_object()->get_meta());
		}

		void on_accountable_changed(messenger::msg_accountable_app_t* msg)
		{
			switch(msg->get_type())
			{
				case messenger::accountable_type_t::create:
                    on_accountable_created(msg);
				break;
				case messenger::accountable_type_t::destroy:
                    on_accountable_destroyed(msg);
				break;
			}
		}

		std::unique_ptr<messenger::instance_t<messenger::msg_accountable_app_t> > messenger_instance;

	};
}

#endif<|endoftext|>


<commit_before>#include "photon_core.h"
#include "photon_input.h"

#include <physfs.h>
#include <libxml/parser.h>

namespace photon{

namespace input{

const xmlChar* operator "" _xml(const char* str, size_t /*length*/){
    return (const xmlChar*)str;
}

photon_input_state LoadInputSingle(xmlNode *node){
    photon_input_state state;
    xmlChar *type_str = xmlGetProp(node, "type"_xml);

    if((xmlStrEqual(type_str, "keyboard"_xml))){
        state.type = photon_input_state::keyboard;

        xmlChar *key_str = xmlGetProp(node, "key"_xml);
        xmlChar *mod_str = xmlGetProp(node, "modifiers"_xml);

        state.key = SDL_GetScancodeFromName((char*)key_str);

        if(xmlStrstr(mod_str, "ctrl"_xml)){
            state.modifiers |= KMOD_CTRL;
        }else if(xmlStrstr(mod_str, "shift"_xml)){
            state.modifiers |= KMOD_SHIFT;
        }else if(xmlStrstr(mod_str, "alt"_xml)){
            state.modifiers |= KMOD_ALT;
        }

        xmlFree(key_str);
        xmlFree(mod_str);
    }else if((xmlStrEqual(type_str, "joystick_button"_xml))){
        state.type = photon_input_state::joystick_button;

        xmlChar *index_str = xmlGetProp(node, "index"_xml);
        state.joystick_input_index = atoi((char*)index_str);

        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "joystick_axis"_xml))){
        state.type = photon_input_state::joystick_axis;

        xmlChar *index_str = xmlGetProp(node, "index"_xml);
        xmlChar *negate_str = xmlGetProp(node, "negate"_xml);
        state.joystick_input_index = atoi((char*)index_str);
        state.axis_input_negate = xmlStrEqual(negate_str, "true"_xml);

        xmlFree(negate_str);
        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "controller_button"_xml))){
        state.type = photon_input_state::gamecontroller_button;

        xmlChar *index_str = xmlGetProp(node, "button"_xml);
        state.controller_button = SDL_GameControllerGetButtonFromString((char*)index_str);

        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "controller_axis"_xml))){
        state.type = photon_input_state::gamecontroller_axis;

        xmlChar *index_str = xmlGetProp(node, "axis"_xml);
        xmlChar *negate_str = xmlGetProp(node, "negate"_xml);
        state.controller_axis = SDL_GameControllerGetAxisFromString((char*)index_str);
        state.axis_input_negate = xmlStrEqual(negate_str, "true"_xml);

        xmlFree(negate_str);
        xmlFree(index_str);
    }
    return state;
}

bool LoadConfig(const std::string &filename, photon_input &input){
    if(PHYSFS_exists(filename.c_str())){
        PHYSFS_File *file;
        long length;
        char *xml_buffer;

        file = PHYSFS_openRead(filename.c_str());
        if(!file){
            PrintToLog("ERROR: unable to open XML input config file \"%s\"", filename.c_str());
            return false;
        }

        length = PHYSFS_fileLength(file);
        xml_buffer = (char*)malloc(length);

        PHYSFS_read(file, xml_buffer, 1, length);
        PHYSFS_close(file);

        xmlDocPtr doc = xmlParseMemory(xml_buffer, length);

        if(doc == nullptr) {
            PrintToLog("ERROR: Unable to load XML input config: Document not parsed successfully!");
            return false;
        }

        xmlNodePtr root = xmlDocGetRootElement(doc);
        if(root == nullptr) {
            PrintToLog("ERROR: Unable to load XML input config: empty document!");
            xmlFreeDoc(doc);
            return false;
        }
        if(xmlStrcmp(root->name, "photon_input"_xml)) {
            PrintToLog("ERROR: Unable to load XML input config: root node not photon_input!");
            xmlFreeDoc(doc);
            return false;
        }
        input.is_valid = false;

        xmlChar *device_str = xmlGetProp(root, "device"_xml);
        xmlChar *guid_str = xmlGetProp(root, "device_guid"_xml);

        xmlFree(device_str);
        xmlFree(guid_str);

        xmlNode *node = root->xmlChildrenNode;

        while(node != nullptr) {
            if((xmlStrEqual(node->name, "interact"_xml))){
                input.interact = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "next_item"_xml))){
                input.next_item = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "previous_item"_xml))){
                input.previous_item = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "open_inventory"_xml))){
                input.open_inventory = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "rotate_clockwise"_xml))){
                input.rotate_clockwise = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "rotate_counter_clockwise"_xml))){
                input.rotate_counter_clockwise = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "zoom_in"_xml))){
                input.zoom_in = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "zoom_out"_xml))){
                input.zoom_out = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_right"_xml))){
                input.move_right = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_left"_xml))){
                input.move_left = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_up"_xml))){
                input.move_up = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_down"_xml))){
                input.move_down = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_right"_xml))){
                input.camera_right = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_left"_xml))){
                input.camera_left = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_up"_xml))){
                input.camera_up = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_down"_xml))){
                input.camera_down = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "pause"_xml))){
                input.pause = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_up"_xml))){
                input.up = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_down"_xml))){
                input.down = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_left"_xml))){
                input.left = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_right"_xml))){
                input.right = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_select"_xml))){
                input.select = LoadInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_back"_xml))){
                input.back = LoadInputSingle(node);
            }
            node = node->next;
        }

        input.is_valid = true;

        free(xml_buffer);
        xmlFreeDoc(doc);

        return true;
    }else{
        PrintToLog("ERROR: Unable to load XML input config: \"%s\" does not exist!", filename.c_str());
    }
    return false;
}

}

}
<commit_msg>rename LoadInputSingle to ParseInputSingle<commit_after>#include "photon_core.h"
#include "photon_input.h"

#include <physfs.h>
#include <libxml/parser.h>

namespace photon{

namespace input{

const xmlChar* operator "" _xml(const char* str, size_t /*length*/){
    return (const xmlChar*)str;
}

photon_input_state ParseInputSingle(xmlNode *node){
    photon_input_state state;
    xmlChar *type_str = xmlGetProp(node, "type"_xml);

    if((xmlStrEqual(type_str, "keyboard"_xml))){
        state.type = photon_input_state::keyboard;

        xmlChar *key_str = xmlGetProp(node, "key"_xml);
        xmlChar *mod_str = xmlGetProp(node, "modifiers"_xml);

        state.key = SDL_GetScancodeFromName((char*)key_str);

        if(xmlStrstr(mod_str, "ctrl"_xml)){
            state.modifiers |= KMOD_CTRL;
        }else if(xmlStrstr(mod_str, "shift"_xml)){
            state.modifiers |= KMOD_SHIFT;
        }else if(xmlStrstr(mod_str, "alt"_xml)){
            state.modifiers |= KMOD_ALT;
        }

        xmlFree(key_str);
        xmlFree(mod_str);
    }else if((xmlStrEqual(type_str, "joystick_button"_xml))){
        state.type = photon_input_state::joystick_button;

        xmlChar *index_str = xmlGetProp(node, "index"_xml);
        state.joystick_input_index = atoi((char*)index_str);

        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "joystick_axis"_xml))){
        state.type = photon_input_state::joystick_axis;

        xmlChar *index_str = xmlGetProp(node, "index"_xml);
        xmlChar *negate_str = xmlGetProp(node, "negate"_xml);
        state.joystick_input_index = atoi((char*)index_str);
        state.axis_input_negate = xmlStrEqual(negate_str, "true"_xml);

        xmlFree(negate_str);
        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "controller_button"_xml))){
        state.type = photon_input_state::gamecontroller_button;

        xmlChar *index_str = xmlGetProp(node, "button"_xml);
        state.controller_button = SDL_GameControllerGetButtonFromString((char*)index_str);

        xmlFree(index_str);
    }else if((xmlStrEqual(type_str, "controller_axis"_xml))){
        state.type = photon_input_state::gamecontroller_axis;

        xmlChar *index_str = xmlGetProp(node, "axis"_xml);
        xmlChar *negate_str = xmlGetProp(node, "negate"_xml);
        state.controller_axis = SDL_GameControllerGetAxisFromString((char*)index_str);
        state.axis_input_negate = xmlStrEqual(negate_str, "true"_xml);

        xmlFree(negate_str);
        xmlFree(index_str);
    }
    return state;
}

bool LoadConfig(const std::string &filename, photon_input &input){
    if(PHYSFS_exists(filename.c_str())){
        PHYSFS_File *file;
        long length;
        char *xml_buffer;

        file = PHYSFS_openRead(filename.c_str());
        if(!file){
            PrintToLog("ERROR: unable to open XML input config file \"%s\"", filename.c_str());
            return false;
        }

        length = PHYSFS_fileLength(file);
        xml_buffer = (char*)malloc(length);

        PHYSFS_read(file, xml_buffer, 1, length);
        PHYSFS_close(file);

        xmlDocPtr doc = xmlParseMemory(xml_buffer, length);

        if(doc == nullptr) {
            PrintToLog("ERROR: Unable to load XML input config: Document not parsed successfully!");
            return false;
        }

        xmlNodePtr root = xmlDocGetRootElement(doc);
        if(root == nullptr) {
            PrintToLog("ERROR: Unable to load XML input config: empty document!");
            xmlFreeDoc(doc);
            return false;
        }
        if(xmlStrcmp(root->name, "photon_input"_xml)) {
            PrintToLog("ERROR: Unable to load XML input config: root node not photon_input!");
            xmlFreeDoc(doc);
            return false;
        }
        input.is_valid = false;

        xmlChar *device_str = xmlGetProp(root, "device"_xml);
        xmlChar *guid_str = xmlGetProp(root, "device_guid"_xml);

        xmlFree(device_str);
        xmlFree(guid_str);

        xmlNode *node = root->xmlChildrenNode;

        while(node != nullptr) {
            if((xmlStrEqual(node->name, "interact"_xml))){
                input.interact = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "next_item"_xml))){
                input.next_item = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "previous_item"_xml))){
                input.previous_item = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "open_inventory"_xml))){
                input.open_inventory = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "rotate_clockwise"_xml))){
                input.rotate_clockwise = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "rotate_counter_clockwise"_xml))){
                input.rotate_counter_clockwise = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "zoom_in"_xml))){
                input.zoom_in = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "zoom_out"_xml))){
                input.zoom_out = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_right"_xml))){
                input.move_right = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_left"_xml))){
                input.move_left = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_up"_xml))){
                input.move_up = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "move_down"_xml))){
                input.move_down = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_right"_xml))){
                input.camera_right = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_left"_xml))){
                input.camera_left = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_up"_xml))){
                input.camera_up = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "camera_down"_xml))){
                input.camera_down = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "pause"_xml))){
                input.pause = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_up"_xml))){
                input.up = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_down"_xml))){
                input.down = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_left"_xml))){
                input.left = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_right"_xml))){
                input.right = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_select"_xml))){
                input.select = ParseInputSingle(node);
            }else if((xmlStrEqual(node->name, "gui_back"_xml))){
                input.back = ParseInputSingle(node);
            }
            node = node->next;
        }

        input.is_valid = true;

        free(xml_buffer);
        xmlFreeDoc(doc);

        return true;
    }else{
        PrintToLog("ERROR: Unable to load XML input config: \"%s\" does not exist!", filename.c_str());
    }
    return false;
}

}

}
<|endoftext|>


<commit_before>/*=============================================================================

Library: CppMicroServices

Copyright (c) The CppMicroServices developers. See the COPYRIGHT
file at the top-level directory of this distribution and at
https://github.com/CppMicroServices/CppMicroServices/COPYRIGHT .

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=============================================================================*/

#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/FrameworkFactory.h"
#include "cppmicroservices/Framework.h"
#include "cppmicroservices/GetBundleContext.h"

#include "TestingConfig.h"
#include "TestingMacros.h"
#include "TestUtils.h"

#include <mutex>
#include <thread>
#include <vector>

using namespace cppmicroservices;

#ifdef US_BUILD_SHARED_LIBS
namespace
{
    std::mutex mutex_io = {};
    std::unique_lock<std::mutex> io_lock()
    {
      return std::unique_lock<std::mutex>(mutex_io);
    }

    // Attempt to get as close an approximation as to how long it takes to install a bundle
    // without having the extra machinery of error handling in the way.
    inline void InstallTestBundleNoErrorHandling(BundleContext frameworkCtx, const std::string& bundleName)
    {
#if defined (US_BUILD_SHARED_LIBS)
        frameworkCtx.InstallBundles(testing::LIB_PATH + testing::DIR_SEP + testing::LIB_PREFIX + bundleName + testing::LIB_EXT);
#else
        US_UNUSED(bundleName);
        frameworkCtx.InstallBundles(testing::BIN_PATH + testing::DIR_SEP + "usFrameworkTestDriver" + testing::EXE_EXT);
#endif
    }

    void TestSerial(const Framework& f)
    {
        // Installing such a small set of bundles doesn't yield significant
        // data about performance. Consider increasing the number of bundles
        // used.
        auto bc = f.GetBundleContext();

        HighPrecisionTimer timer;
        timer.Start();
        InstallTestBundleNoErrorHandling(bc, "TestBundleA");
        InstallTestBundleNoErrorHandling(bc, "TestBundleA2");
        InstallTestBundleNoErrorHandling(bc, "TestBundleB");
#ifdef US_ENABLE_THREADING_SUPPORT
        InstallTestBundleNoErrorHandling(bc, "TestBundleC1");
#endif
        InstallTestBundleNoErrorHandling(bc, "TestBundleH");
        InstallTestBundleNoErrorHandling(bc, "TestBundleLQ");
        InstallTestBundleNoErrorHandling(bc, "TestBundleM");
        InstallTestBundleNoErrorHandling(bc, "TestBundleR");
        InstallTestBundleNoErrorHandling(bc, "TestBundleRA");
        InstallTestBundleNoErrorHandling(bc, "TestBundleRL");
        InstallTestBundleNoErrorHandling(bc, "TestBundleS");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL1");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL3");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL4");

        long long elapsedTimeInMilliSeconds = timer.ElapsedMilli();
        io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] Time elapsed to install 12 new bundles: " << elapsedTimeInMilliSeconds << " milliseconds");

        elapsedTimeInMilliSeconds = 0;

        auto bundles = bc.GetBundles();
        for (auto& bundle : bundles)
        {
            timer.Start();
            try
            {
              bundle.Start();
            }
            catch (const std::exception& e)
            {
              io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] exception: " << e.what());
            }

            elapsedTimeInMilliSeconds += timer.ElapsedMilli();
        }

        io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] Time elapsed to start 12 bundles: " << elapsedTimeInMilliSeconds << " milliseconds");
    }

#ifdef US_ENABLE_THREADING_SUPPORT
    void TestConcurrent(const Framework& f)
    {
        // This is by no means a "real world" example. At best it is a simulation to test
        // the performance of concurrent access to the bundle registry.
        // At any point in which real customer usage in a concurrent way becomes known,
        // it would be ideal to model it as a test.

        std::size_t numTestBundles = 16;  // 14 test bundles + 1 statically linked bundle + the system bundle
        numTestBundles += 1; // main
        const int numTestThreads = 100;
        std::vector<std::thread> threads;
        for (int i = 0; i < numTestThreads; ++i)
        {
            threads.emplace_back(TestSerial, f);
            threads.emplace_back([f]{ f.GetBundleContext().GetBundles(); });
        }

        for (auto& th : threads) th.join();
        US_TEST_CONDITION(numTestBundles == f.GetBundleContext().GetBundles().size(), "Test for correct number of installed bundles")
    }
#endif

}   // end anonymous namespace
#endif

int BundleRegistryPerformanceTest(int /*argc*/, char* /*argv*/[])
{
    US_TEST_BEGIN("BundleRegistryPerformanceTest")

    FrameworkFactory factory;
    auto framework = factory.NewFramework();
    framework.Start();
#ifdef US_BUILD_SHARED_LIBS
    US_TEST_OUTPUT(<< "Testing serial installation of bundles");
    TestSerial(framework);

    for (auto bundle : framework.GetBundleContext().GetBundles())
    {
        if (bundle.GetBundleId() != 0 && bundle.GetSymbolicName() != "main")
        {
            bundle.Uninstall();
        }
    }
#ifdef US_ENABLE_THREADING_SUPPORT
    US_TEST_OUTPUT(<< "Testing concurrent installation of bundles");
    TestConcurrent(framework);
#endif
#endif
    framework.Stop();

    US_TEST_END()
}
<commit_msg>Use less threads in unit test to avoid running into timeouts on Travis CI.<commit_after>/*=============================================================================

Library: CppMicroServices

Copyright (c) The CppMicroServices developers. See the COPYRIGHT
file at the top-level directory of this distribution and at
https://github.com/CppMicroServices/CppMicroServices/COPYRIGHT .

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=============================================================================*/

#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/FrameworkFactory.h"
#include "cppmicroservices/Framework.h"
#include "cppmicroservices/GetBundleContext.h"

#include "TestingConfig.h"
#include "TestingMacros.h"
#include "TestUtils.h"

#include <mutex>
#include <thread>
#include <vector>

using namespace cppmicroservices;

#ifdef US_BUILD_SHARED_LIBS
namespace
{
    std::mutex mutex_io = {};
    std::unique_lock<std::mutex> io_lock()
    {
      return std::unique_lock<std::mutex>(mutex_io);
    }

    // Attempt to get as close an approximation as to how long it takes to install a bundle
    // without having the extra machinery of error handling in the way.
    inline void InstallTestBundleNoErrorHandling(BundleContext frameworkCtx, const std::string& bundleName)
    {
#if defined (US_BUILD_SHARED_LIBS)
        frameworkCtx.InstallBundles(testing::LIB_PATH + testing::DIR_SEP + testing::LIB_PREFIX + bundleName + testing::LIB_EXT);
#else
        US_UNUSED(bundleName);
        frameworkCtx.InstallBundles(testing::BIN_PATH + testing::DIR_SEP + "usFrameworkTestDriver" + testing::EXE_EXT);
#endif
    }

    void TestSerial(const Framework& f)
    {
        // Installing such a small set of bundles doesn't yield significant
        // data about performance. Consider increasing the number of bundles
        // used.
        auto bc = f.GetBundleContext();

        HighPrecisionTimer timer;
        timer.Start();
        InstallTestBundleNoErrorHandling(bc, "TestBundleA");
        InstallTestBundleNoErrorHandling(bc, "TestBundleA2");
        InstallTestBundleNoErrorHandling(bc, "TestBundleB");
#ifdef US_ENABLE_THREADING_SUPPORT
        InstallTestBundleNoErrorHandling(bc, "TestBundleC1");
#endif
        InstallTestBundleNoErrorHandling(bc, "TestBundleH");
        InstallTestBundleNoErrorHandling(bc, "TestBundleLQ");
        InstallTestBundleNoErrorHandling(bc, "TestBundleM");
        InstallTestBundleNoErrorHandling(bc, "TestBundleR");
        InstallTestBundleNoErrorHandling(bc, "TestBundleRA");
        InstallTestBundleNoErrorHandling(bc, "TestBundleRL");
        InstallTestBundleNoErrorHandling(bc, "TestBundleS");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL1");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL3");
        InstallTestBundleNoErrorHandling(bc, "TestBundleSL4");

        long long elapsedTimeInMilliSeconds = timer.ElapsedMilli();
        io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] Time elapsed to install 12 new bundles: " << elapsedTimeInMilliSeconds << " milliseconds");

        elapsedTimeInMilliSeconds = 0;

        auto bundles = bc.GetBundles();
        for (auto& bundle : bundles)
        {
            timer.Start();
            try
            {
              bundle.Start();
            }
            catch (const std::exception& e)
            {
              io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] exception: " << e.what());
            }

            elapsedTimeInMilliSeconds += timer.ElapsedMilli();
        }

        io_lock(), US_TEST_OUTPUT(<< "[thread " << std::this_thread::get_id() << "] Time elapsed to start 12 bundles: " << elapsedTimeInMilliSeconds << " milliseconds");
    }

#ifdef US_ENABLE_THREADING_SUPPORT
    void TestConcurrent(const Framework& f)
    {
        // This is by no means a "real world" example. At best it is a simulation to test
        // the performance of concurrent access to the bundle registry.
        // At any point in which real customer usage in a concurrent way becomes known,
        // it would be ideal to model it as a test.

        std::size_t numTestBundles = 16;  // 14 test bundles + 1 statically linked bundle + the system bundle
        numTestBundles += 1; // main
        const int numTestThreads = 50;
        std::vector<std::thread> threads;
        for (int i = 0; i < numTestThreads; ++i)
        {
            threads.emplace_back(TestSerial, f);
            threads.emplace_back([f]{ f.GetBundleContext().GetBundles(); });
        }

        for (auto& th : threads) th.join();
        US_TEST_CONDITION(numTestBundles == f.GetBundleContext().GetBundles().size(), "Test for correct number of installed bundles")
    }
#endif

}   // end anonymous namespace
#endif

int BundleRegistryPerformanceTest(int /*argc*/, char* /*argv*/[])
{
    US_TEST_BEGIN("BundleRegistryPerformanceTest")

    FrameworkFactory factory;
    auto framework = factory.NewFramework();
    framework.Start();
#ifdef US_BUILD_SHARED_LIBS
    US_TEST_OUTPUT(<< "Testing serial installation of bundles");
    TestSerial(framework);

    for (auto bundle : framework.GetBundleContext().GetBundles())
    {
        if (bundle.GetBundleId() != 0 && bundle.GetSymbolicName() != "main")
        {
            bundle.Uninstall();
        }
    }
#ifdef US_ENABLE_THREADING_SUPPORT
    US_TEST_OUTPUT(<< "Testing concurrent installation of bundles");
    TestConcurrent(framework);
#endif
#endif
    framework.Stop();

    US_TEST_END()
}
<|endoftext|>