The multithread.c example program is for use on the Linux platform.
This sample program demonstrates the use of multiple eduction sessions associated with a single eduction engine running in parallel.
This program takes arguments of the names of the text files to process. The program has the following stages:
The worker thread starts with the eduction engine and the text file. This worker thread:
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <malloc.h> #include <string.h> #include <pthread.h> #include <edk.h> /* * Create an app that uses multiple sessions in parallel * Number of sessions depends on the number of input files */ // Data to pass to each worker thread typedef struct thread_data { char* file; EdkEngineHandle engine; } t_thread_data; // The worker thread function // Creates a session using the engine handle // Processes the the input file static void* WorkProc(void* pvArgs) { t_thread_data* p = (t_thread_data*)pvArgs; EdkEngineHandle engine = p->engine; char* file = p->file; size_t bytesRead; char* buf; struct stat fnInfo; if (stat(file, &fnInfo)) { printf("Unable to stat input file.\n"); return NULL; } size_t fileSize = fnInfo.st_size; if (!fileSize) { printf("File size of input file is zero!\n"); return NULL; } FILE *f; f = fopen(file, "rb"); if (!f) { printf("Can't open input file!\n"); return NULL; } // Read input file to buffer // Note that the input must be UTF-8 encoded. buf = (char*)malloc(fileSize * sizeof(char)); bytesRead = fread(buf, 1, fileSize, f); if (bytesRead < fileSize) { fclose(f); f = NULL; printf("Unable to read input file!\n"); return NULL; } // Create a session and process the input file EdkError error; EdkSessionHandle session = NULL; if (EdkSuccess != (error = EdkSessionCreate(engine, &session))) { printf("Error: Unable to create session, error code = %d\n", error); return NULL; } if (EdkSuccess != (error = EdkAddInputText(session, buf, bytesRead, true))) { printf("Unable to add input text, error code = %d\n", error); return NULL; } else { while(EdkSuccess == EdkGetNextMatch(session)) { // For each match found, do this ... const char* szMatch = NULL; EdkGetMatchText(session, &szMatch); printf("Match found: %s\n", szMatch); } } // Destroy the session and exit when done EdkSessionDestroy(session); session = NULL; free(buf); return NULL; } // Main function // Reads arguments from command line as input files // Creates one thread to process each input file int main(int argc, char **argv) { char *license; struct stat fnLicense; off_t len; FILE *f; size_t itemsRead; // Input files are specified at the command line // One thread will be created to process every input file if (argc <= 1) { printf("No input file specified.\n"); return -1; } // Licensing if (stat("licensekey.dat", &fnLicense)) { printf("Unable to stat license file.\n"); return -1; } len = fnLicense.st_size; if (!len) { printf("Zero byte file size for license file.\n"); return -1; } f = fopen("licensekey.dat", "rb"); if (!f) { printf("Unable to open license file.\n"); return -1; } license = (char*)malloc(len+1); itemsRead = fread(license, 1, len, f); *(license+len) = '\0'; fclose(f); if (itemsRead < (size_t)len) { free(license); printf("Unable to read license.\n"); return -1; } if (!license) { return -1; } printf("INFO: License read.\n"); // Create the eduction engine EdkError error; EdkEngineHandle engine = NULL; if (EdkSuccess != (error = EdkEngineCreate(&engine))) { printf("Error: Can't create engine, error code = %d.\n", error); return -1; } if (EdkSuccess != (error = EdkSetLicenseKey(engine, license))) { printf("Error: Can't set license key, error code = %d.\n", error); free(license); EdkEngineDestroy(engine); return -1; } printf("INFO: License validated.\n"); free(license); // Load the resource file - change if necessary if (EdkSuccess != (error = EdkLoadResourceFile(engine, "company_eng.ecr"))) { printf("Error: Can't load resource file, error code = %d.\n", error); EdkEngineDestroy(engine); return -1; } printf("INFO: Resource file loaded.\n"); // Add target entity - change if necessary if (EdkSuccess != (error = EdkAddTargetEntity(engine, "company/name/eng"))) { printf("Error: Can't add entity, error cdoe = %d.\n", error); EdkEngineDestroy(engine); return -1; } printf("INFO: Entity added.\n"); // Prepare the worker threads size_t nThreads = argc - 1; pthread_t* threadId = (pthread_t*)calloc(nThreads, sizeof(pthread_t)); void* tmp = calloc(nThreads, sizeof(t_thread_data)); t_thread_data* threadData = (t_thread_data*)tmp; int ii = 0; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128000); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // Start the threads // Each thread uses a session to process an input file for(ii=0;ii<nThreads;ii++) { threadData[ii].engine = engine; threadData[ii].file = argv[ii + 1]; pthread_create(&threadId[ii], &attr, WorkProc, (void*)&threadData[ii]); } // Join the threads when done for (ii = 0; ii < nThreads; ii++) { if (threadId[ii]) { void *pvres; pthread_join(threadId[ii], &pvres); } } free(threadId); free(threadData); EdkEngineDestroy(engine); printf("INFO: Done\n"); return 1; }
|