Hello All
I have developed a java wrapper over the mozilla html parser. It is
working great except for an annoying multithreading issue. I am hoping
that someone can help me with it.
The problem is quite simple. At first , when the parser is
initializes , it starts a initXPCOM2() method to initialize the XPCOM
interface. if i then ask for a nsParser instance from that thread it
will give it to me with no problem and thus from that thread i can do
whatever i want.
The problem begins when i have another thread that is trying to get an
instance of nsParser. the code throws an assertion exception and tells
me that this is the class is thread safe . here is the error :
###!!! ASSERTION: nsParser not thread-safe:
'_mOwningThread.GetThread() == PR_GetCurrentThread()', file src
\nsParser.cpp, line 77
I have tried to use proxies but i didn't manage to get it right,
I have two questions :
1. is it possible at all to do what i am trying to do ? Is it possible
to parse two html pages asynchronously, from two different native
threads ?
2. I have another class that is apperantly not thread safe , it is
called JavaContentSink and it extends the nsLoggingSink class. when i
try to have multiple instances of it i am getting a huge memory leak ,
and thus i have to have only one instance of the content sink ... How
can get the xpcom to delete the references to the JavaContentSink
instances if i am not using the doCreateInstance() mechanism , but
just instantiate the object myslef directly in the code ?
Here is the code that of the MozillaParser.cpp that is not working
#include <jni.h>
#include "MozillaParser.h"
#include "JavaContentSink.h"
#include "nsXPCOM.h"
#include "nsIComponentManager.h"
#include "nsParserCIID.h"
#include "nsIParser.h"
#include "nsILoggingSink.h"
#include "nsIInputStream.h"
#include "nsILocalFile.h"
#include "nsEmbedString.h"
#include "nsIProxyObjectManager.h"
#include "nsParser.h"
// Class IID's
static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID);
static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID);
static
NS_DEFINE_CID(kProxyObjectManagerCID,NS_PROXYEVENT_MANAGER_CID);
// JAVA Exception constants :
const char *PARSER_EXCEPTION="com/dappit/Dapper/parser/
ParserException";
const char *PARSER_INITIALIZATION_EXCEPTION="com/dappit/Dapper/parser/
ParserInitializationException";
// Java helper function :Generate an exception :
void generateException(JNIEnv * env , const char *exceptionName , char
*message){
env->ExceptionDescribe();
env->ExceptionClear();
jclass newExcCls = env->FindClass(exceptionName);
if (newExcCls == 0) /* Unable to find the new exception class, give
up. */
{
return;
}
env->ThrowNew( newExcCls, message);
}
void generateException(JNIEnv * env , char *message ){
generateException(env,PARSER_EXCEPTION,message);
}
//static nsCOMPtr<nsIParser> parser;
//static nsCOMPtr<nsIDTD> dtd;
static nsIContentSink* sink;
static JavaContentSink javaContentSink;
JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_initXPCOM
(JNIEnv *env, jclass , jstring componentBaseString)
{
jboolean iscopy;
const char *componentBaseInput = env-
>GetStringUTFChars(componentBaseString , &iscopy);
int inputBaseLength = (int)env->GetStringLength(componentBaseString);
printf("Initializing XPCOM from location : %s...\n" ,
componentBaseInput);
nsresult rv;
nsCOMPtr<nsILocalFile> file;
nsString componentBaseNsString;
componentBaseNsString.AppendWithConversion(componentBaseInput ,
inputBaseLength );
rv = NS_NewLocalFile(nsEmbedString(componentBaseNsString), PR_FALSE,
getter_AddRefs(file));
rv = NS_InitXPCOM2(nsnull, file , nsnull);
env->ReleaseStringUTFChars(componentBaseString , componentBaseInput);
if (NS_FAILED(rv))
{
char errMessage[100];
sprintf(errMessage , "%x" , rv );
generateException(env , PARSER_INITIALIZATION_EXCEPTION ,
"Starting
XPCOM Failed : %s");
}
nsresult result = NS_OK;
sink = &javaContentSink;
}
JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_setDebug
(JNIEnv *, jobject, jboolean aDoDebug)
{
JavaContentSink::setDebug((bool)aDoDebug);
}
JNIEXPORT void JNICALL
Java_com_dappit_Dapper_parser_MozillaParser_parseHtml
(JNIEnv *env, jobject mozillaParserObject, jstring stringToParse)
{
jboolean iscopy;
const char *parserInput = env->GetStringUTFChars(stringToParse,
&iscopy);
int htmlLength = (int)env->GetStringLength(stringToParse);
// printf("Got html : %s\nString Size:%d\n" , parserInput ,
htmlLength);
printf("Parsing Html...");
// Create a parser
nsresult result = NS_OK;
nsCOMPtr<nsIParser> parser(do_CreateInstance(kParserCID, &result));
if (NS_FAILED(result)) {
printf("\nUnable to create a parser : %x \n" , result);
return;
}
//nsIContentSink* sink;
//JavaContentSink javaContentSink;
javaContentSink.setJavaEnviroment(env , mozillaParserObject);
// Create a dtd
nsCOMPtr<nsIDTD> dtd(do_CreateInstance(kNavDTDCID, &result));
if(NS_FAILED(result)) {
printf("Unable to create a dtd\n");
return;
}
parser->RegisterDTD(dtd);
//printf("creating a stream out of input html...\n");
nsString stream;
stream.AppendWithConversion(parserInput , htmlLength);
// printf("Preparing parser for parsing...\n");
// sink = &javaContentSink;
parser->SetContentSink(sink);
// printf("parsing...\n");
parser->Parse(stream, 0, NS_LITERAL_CSTRING("text/html"), PR_FALSE,
PR_TRUE);
//parser->SetContentSink(nsnull);
//sink->SetParser(nsnull);
env->ReleaseStringUTFChars(stringToParse , parserInput);
}
Thanks
Ohad Serfaty
_______________________________________________
dev-embedding mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-embedding