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;
}
|
|