瀏覽代碼

Fixed ability to cancel downloads

Brian Fiete 5 年之前
父節點
當前提交
d26e2957b0

+ 14 - 1
BeefySysLib/util/ThreadPool.cpp

@@ -8,6 +8,7 @@ static BF_TLS_DECLSPEC ThreadPool* gPoolParent;
 ThreadPool::Thread::Thread()
 {
 	mCurJobThreadId = -1;
+	mActiveJob = NULL;
 }
 
 ThreadPool::Thread::~Thread()
@@ -34,9 +35,10 @@ void ThreadPool::Thread::Proc()
 			{
 				job = mThreadPool->mJobs[0];
 				job->mProcessing = true;
-				mThreadPool->mJobs.RemoveAt(0);
+				mThreadPool->mJobs.RemoveAt(0);				
 			}
 			
+			mActiveJob = job;
 			if (job == NULL)
 				mCurJobThreadId = -1;
 			else
@@ -76,6 +78,7 @@ void ThreadPool::Thread::Proc()
 
 		// Run dtor synchronized
 		AutoCrit autoCrit(mThreadPool->mCritSect);
+		mActiveJob = NULL;
 		delete job;
 	}	
 }
@@ -176,4 +179,14 @@ void ThreadPool::AddJob(BfpThreadStartProc proc, void* param, int maxWorkersPerP
 bool ThreadPool::IsInJob()
 {
 	return gPoolParent == this;
+}
+
+void ThreadPool::CancelAll()
+{
+	AutoCrit autoCrit(mCritSect);
+	for (auto job : mJobs)
+		job->Cancel();
+	for (auto thread : mThreads)
+		if (thread->mActiveJob != NULL)
+			thread->mActiveJob->Cancel();
 }

+ 4 - 0
BeefySysLib/util/ThreadPool.h

@@ -9,12 +9,15 @@ NS_BF_BEGIN
 class ThreadPool
 {
 public:
+	class Job;
+
 	class Thread
 	{
 	public:
 		ThreadPool* mThreadPool;
 		BfpThread* mBfpThread;
 		BfpThreadId mCurJobThreadId;
+		Job* mActiveJob;
 
 	public:
 		Thread();
@@ -85,6 +88,7 @@ public:
 	void AddJob(Job* job, int maxWorkersPerProviderThread = 0x7FFFFFFF);
 	void AddJob(BfpThreadStartProc proc, void* param, int maxWorkersPerProviderThread = 0x7FFFFFFF);
 	bool IsInJob();
+	void CancelAll();
 };
 
 NS_BF_END

+ 1 - 1
IDE/BeefProj.toml

@@ -27,7 +27,7 @@ TargetDirectory = "$(WorkspaceDir)/dist"
 TargetName = "BeefIDE_d"
 OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib"
 CLibType = "Dynamic"
-DebugCommandArguments = "-test=scripts\\Minidump.txt -testNoExit -verbosity=Diagnostic"
+DebugCommandArguments = "-test=scripts\\Minidump.txt -testNoExit -verbosity=diagnostic"
 DebugWorkingDirectory = "c:\\Beef\\IDE\\Tests\\EmptyTest"
 EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
 

+ 1 - 2
IDE/Tests/EmptyTest/scripts/Minidump.txt

@@ -1,6 +1,5 @@
 SetSymSrvOptions("C:/SymCache", "http://symbols.beeflang.org/\nhttps://msdl.microsoft.com/download/symbols", "TempCache")
-#SetSymSrvOptions("C:/SymCache", "https://msdl.microsoft.com/download/symbols\nhttps://chromium-browser-symsrv.commondatastorage.googleapis.com", "TempCache")
-#SetSymSrvOptions("C:/SymCache", "https://msdl.microsoft.com/download/symbols\nhttps://chromium-browser-symsrv.commondatastorage.googleapis.com", "None")
+#SetSymSrvOptions("C:/SymCache", "http://127.0.0.1:8042", "TempCache")
 
 OpenCrashDump("dumps/Chrome1.dmp")
 WaitForPaused()

+ 3 - 1
IDE/src/IDEApp.bf

@@ -6292,6 +6292,8 @@ namespace IDE
 					    mVerbosity = .Detailed;
 					else if (value == "diagnostic")
 					    mVerbosity = .Diagnostic;
+					else
+						Fail(scope String()..AppendF("Invalid verbosity option: {}", value));
 				case "-workspace","-proddir":
 					var relDir = scope String(value);
 					if ((relDir.EndsWith("\\")) || relDir.EndsWith("\""))
@@ -10465,7 +10467,7 @@ namespace IDE
 					bool isOutput = (cmd == "msg") || (cmd == "dbgEvalMsg") || (cmd == "log");
 					if (cmd == "msgLo")
 					{
-						if (mVerbosity <= .Diagnostic)
+						if (mVerbosity < .Diagnostic)
 							continue;
 						isOutput = true;
 					}

+ 54 - 11
IDEHelper/NetManager.cpp

@@ -9,6 +9,7 @@ USING_NS_BF;
 #ifdef BF_CURL
 #define CURL_STATICLIB
 #include "curl/curl.h"
+#include "curl/multi.h"
 
 static int TransferInfoCallback(void* userp,
 	curl_off_t dltotal, curl_off_t dlnow,
@@ -80,8 +81,18 @@ static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb, voi
 
 void NetRequest::Cleanup()
 {
+	if (mCURLMulti != NULL)
+	{
+		curl_multi_remove_handle(mCURLMulti, mCURL);		
+	}
+
 	if (mCURL != NULL)
 		curl_easy_cleanup(mCURL);
+
+	if (mCURLMulti != NULL)
+	{
+		curl_multi_cleanup(mCURLMulti);
+	}
 }
 
 void NetRequest::Perform()
@@ -98,7 +109,9 @@ void NetRequest::Perform()
 	mNetManager->mDebugManager->OutputRawMessage(StrFormat("msgLo Getting '%s'\n", mURL.c_str()));
 
 	mOutTempPath = mOutPath + "__partial";	
-		
+	
+	mCURLMulti = curl_multi_init();
+
 	mCURL = curl_easy_init();	
 
 	if (mShowTracking)
@@ -115,13 +128,37 @@ void NetRequest::Perform()
 	curl_easy_setopt(mCURL, CURLOPT_XFERINFOFUNCTION, TransferInfoCallback);
 	curl_easy_setopt(mCURL, CURLOPT_FOLLOWLOCATION, 1L);
 	curl_easy_setopt(mCURL, CURLOPT_NOPROGRESS, 0L);
-	auto result = curl_easy_perform(mCURL);
+	//auto result = curl_easy_perform(mCURL);
 
-	if (result != CURLE_OK)
+	CURLMcode mcode = curl_multi_add_handle(mCURLMulti, mCURL);
+	if (mcode != CURLM_OK)
 	{
 		mFailed = true;
 		return;
 	}
+	
+	while (true)
+	{ 
+		int activeCount = 0;
+		curl_multi_perform(mCURLMulti, &activeCount);
+		if (activeCount == 0)
+			break;
+
+		int waitRet = 0;
+		curl_multi_wait(mCURLMulti, NULL, 0, 20, &waitRet);		
+
+		if (mCancelling)
+		{
+			mFailed = true;
+			return;
+		}
+	}
+
+// 	if (result != CURLE_OK)
+// 	{
+// 		mFailed = true;
+// 		return;
+// 	}
 
 	long response_code = 0;
 	curl_easy_getinfo(mCURL, CURLINFO_RESPONSE_CODE, &response_code);
@@ -375,6 +412,7 @@ void NetManagerThread()
 NetManager::NetManager() : mThreadPool(8, 1*1024*1024)
 {
 	mWaitingResult = NULL;
+	mWaitingRequest = NULL;
 }
 
 NetManager::~NetManager()
@@ -458,7 +496,7 @@ bool NetManager::Get(const StringImpl& url, const StringImpl& destPath)
 						break;
 					}
 
-					mWaitingResult = netResult;
+					mWaitingResult = netResult;					
 					netResult->mCurRequest->ShowTracking();
 				}				
 			}
@@ -474,10 +512,16 @@ bool NetManager::Get(const StringImpl& url, const StringImpl& destPath)
 	}
 
 	// Perform this in the requesting thread
+	{
+		AutoCrit autoCrit(mThreadPool.mCritSect);
+		mWaitingRequest = netRequest;
+	}
+
 	netRequest->mShowTracking = true;
 	netRequest->Perform();
 
 	AutoCrit autoCrit(mThreadPool.mCritSect);
+	mWaitingRequest = NULL;
 	auto netResult = netRequest->mResult;
 	delete netRequest;
 
@@ -490,11 +534,9 @@ bool NetManager::Get(const StringImpl& url, const StringImpl& destPath)
 void NetManager::CancelAll()
 {
 	AutoCrit autoCrit(mThreadPool.mCritSect);
-	for (auto job : mThreadPool.mJobs)
-	{
-		auto netRequest = (NetRequest*)job;
-		netRequest->Cancel();
-	}
+	if (mWaitingRequest != NULL)
+		mWaitingRequest->Cancel();
+	mThreadPool.CancelAll();	
 }
 
 void NetManager::Clear()
@@ -528,8 +570,9 @@ void NetManager::Clear()
 void NetManager::CancelCurrent()
 {
 	AutoCrit autoCrit(mThreadPool.mCritSect);
-
-	if ((mWaitingResult != NULL) && (mWaitingResult->mCurRequest != NULL))
+	if (mWaitingRequest != NULL)
+		mWaitingRequest->Cancel();
+	else if ((mWaitingResult != NULL) && (mWaitingResult->mCurRequest != NULL))
 		mWaitingResult->mCurRequest->Cancel();
 }
 

+ 5 - 1
IDEHelper/NetManager.h

@@ -17,6 +17,7 @@ class NetResult;
 
 #ifdef BF_CURL
 typedef void CURL;
+typedef void CURLM;
 #endif
 
 class NetRequest : public ThreadPool::Job
@@ -30,9 +31,10 @@ public:
 	FileStream mOutFile;
 #ifdef BF_CURL
 	CURL* mCURL;
+	CURLM* mCURLMulti;
 #else
 #endif
-	bool mCancelling;
+	volatile bool mCancelling;
 	bool mFailed;		
 	String mError;
 	uint32 mLastUpdateTick;
@@ -45,6 +47,7 @@ public:
 		mLastUpdateTick = 0;
 #ifdef BF_CURL
 		mCURL = NULL;
+		mCURLMulti = NULL;
 #else
 #endif
 		mCancelling = false;
@@ -90,6 +93,7 @@ public:
 	Array<NetResult*> mOldResults;
 	SyncEvent mRequestDoneEvent;
 	NetResult* mWaitingResult;
+	NetRequest* mWaitingRequest;
 
 public:
 	NetManager();