diff --git a/TODO.txt b/TODO.txt index 13f9020..f79a9d0 100644 --- a/TODO.txt +++ b/TODO.txt @@ -8,9 +8,16 @@ Important Features: Important improvements: +* Stop locking during updates +* Stop memory accumulation + * A few MB accumulate on every update + * ime it's than .1 MB per feed― but if you have several feeds, it can + accumulate to a hefty sum after some time. In my case, with ~40 feeds + and updates every 30 minutes, it got to about 200MB after a week or + so. + * _Huge_ problem, but I haven't had luck figuring it out yet… * Proper queue list (see Multiple downloads at once?) * No hardcoded paths -* Remove unnecessary `new`-- make sure to delete everything * General input sanitization * File error-handling * e.g., Utils.cpp's userFileError diff --git a/src/App.cpp b/src/App.cpp index 8729df0..439f327 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -25,19 +25,6 @@ #include "Util.h" -int -main(int argc, char** argv) -{ - srand(time(0)); - installMimeTypes(); - - App* app = new App(); - app->Run(); - app->fPreferences->Save(); - return 0; -} - - App::App() : BApplication("application/x-vnd.Pogger") { fPreferences = new Preferences; @@ -49,14 +36,14 @@ App::App() : BApplication("application/x-vnd.Pogger") fNotifier = new Notifier(); fFeedController = new FeedController(); - BMessage* updateMessage = new BMessage(kUpdateSubscribed); + BMessage updateMessage(kUpdateSubscribed); int64 interval = fPreferences->UpdateInterval(); int32 count = -1; if (interval == -1) count = 0; // else -// MessageReceived(updateMessage); +// MessageReceived(&updateMessage); fUpdateRunner = new BMessageRunner(this, updateMessage, interval, count); } @@ -106,6 +93,19 @@ App::MessageReceived(BMessage* msg) } +bool +App::QuitRequested() +{ + delete fUpdateRunner, fFeedController, fNotifier; + if (fMainWindow->Lock()) + fMainWindow->Quit(); + + fPreferences->Save(); + delete fPreferences; + return true; +} + + void App::ArgvReceived(int32 argc, char** argv) { @@ -121,10 +121,10 @@ App::ArgvReceived(int32 argc, char** argv) else if (BUrl(argv[i]).IsValid()) { Feed* newFeed = new Feed(BUrl(argv[i])); - BMessage* enqueue = new BMessage(kEnqueueFeed); - enqueue->AddData("feeds", B_RAW_TYPE, (void*)newFeed, sizeof(Feed)); + BMessage enqueue = BMessage(kEnqueueFeed); + enqueue.AddData("feeds", B_RAW_TYPE, (void*)newFeed, sizeof(Feed)); - MessageReceived(enqueue); + MessageReceived(&enqueue); } } RefsReceived(&refMsg); @@ -216,3 +216,15 @@ App::_OpenSourceFile(BMessage* refMessage) const char* configPath = "/boot/home/config/settings/Pogger/"; +int +main(int argc, char** argv) +{ + srand(time(0)); + installMimeTypes(); + + App* app = new App(); + app->Run(); + return 0; +} + + diff --git a/src/App.h b/src/App.h index 80139a3..3a45cab 100644 --- a/src/App.h +++ b/src/App.h @@ -20,8 +20,11 @@ class Notifier; class App : public BApplication { public: - App(void); + App(); + void MessageReceived(BMessage* msg); + bool QuitRequested(); + void ArgvReceived(int32 argc, char** argv); void RefsReceived(BMessage* message); diff --git a/src/AtomFeed.cpp b/src/AtomFeed.cpp index 44ef198..0b389d1 100644 --- a/src/AtomFeed.cpp +++ b/src/AtomFeed.cpp @@ -75,8 +75,7 @@ AtomFeed::RootParse(tinyxml2::XMLElement* xfeed) void AtomFeed::EntryParse(tinyxml2::XMLElement* xentry) { - Entry* newEntry = (Entry*)malloc(sizeof(Entry)); - newEntry = new Entry(); + Entry* newEntry = new Entry(); tinyxml2::XMLElement* xcontent = xentry->FirstChildElement("content"); tinyxml2::XMLElement* xmedia = xentry->FirstChildElement("media:group"); diff --git a/src/Entry.cpp b/src/Entry.cpp index b73fc19..398dc29 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -23,32 +23,36 @@ Entry::Entry() } +Entry::~Entry() +{} + + bool Entry::Filetize(BDirectory outDir) { - BFile* file = new BFile(title.String(), B_READ_WRITE); + BFile file(title.String(), B_READ_WRITE); time_t tt_date = date.Time_t(); - outDir.CreateFile(title.String(), file); + outDir.CreateFile(title.String(), &file); BString betype = BString("text/x-feed-entry"); - file->WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(), + file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(), betype.CountChars() + 1); - file->WriteAttr("Feed:name", B_STRING_TYPE, 0, + file.WriteAttr("Feed:name", B_STRING_TYPE, 0, title.String(), title.CountChars()); - file->WriteAttr("Feed:description", B_STRING_TYPE, 0, + file.WriteAttr("Feed:description", B_STRING_TYPE, 0, description.String(), description.CountChars()); - file->WriteAttr("Feed:source", B_STRING_TYPE, 0, + file.WriteAttr("Feed:source", B_STRING_TYPE, 0, feedTitle.String(), feedTitle.CountChars()); - file->WriteAttr("META:url", B_STRING_TYPE, 0, postUrl.String(), + file.WriteAttr("META:url", B_STRING_TYPE, 0, postUrl.String(), postUrl.CountChars()); if (date != NULL) { - file->WriteAttr("Feed:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t)); + file.WriteAttr("Feed:when", B_TIME_TYPE, 0, &tt_date, sizeof(time_t)); } - file->Write(content.String(), content.Length()); + file.Write(content.String(), content.Length()); return false; } diff --git a/src/Entry.h b/src/Entry.h index a24298b..ed05a51 100644 --- a/src/Entry.h +++ b/src/Entry.h @@ -18,6 +18,7 @@ class Entry { public: Entry(); + ~Entry(); bool Filetize(BDirectory outDir); diff --git a/src/Feed.cpp b/src/Feed.cpp index cf9f068..dc6331d 100644 --- a/src/Feed.cpp +++ b/src/Feed.cpp @@ -86,6 +86,13 @@ Feed::Feed() } +Feed::~Feed() +{ + for (int i = entries.CountItems(); i >= 0; i--) + delete ((Entry*)entries.RemoveItem(i)); +} + + void Feed::Parse() { diff --git a/src/Feed.h b/src/Feed.h index f1cd13c..6817dd1 100644 --- a/src/Feed.h +++ b/src/Feed.h @@ -27,6 +27,8 @@ public: Feed(Feed*); Feed(); + ~Feed(); + virtual void Parse(); BList GetEntries(); diff --git a/src/FeedController.cpp b/src/FeedController.cpp index aabbe13..ac28dd4 100644 --- a/src/FeedController.cpp +++ b/src/FeedController.cpp @@ -60,10 +60,10 @@ FeedController::MessageReceived(BMessage* msg) { BList subFeeds = SubscribedFeeds(); for (int i = 0; i < subFeeds.CountItems(); i++) { - BMessage* getFeed = new BMessage(kEnqueueFeed); - getFeed->AddData("feeds", B_RAW_TYPE, subFeeds.ItemAt(i), + BMessage getFeed(kEnqueueFeed); + getFeed.AddData("feeds", B_RAW_TYPE, subFeeds.ItemAt(i), sizeof(Feed)); - ((App*)be_app)->MessageReceived(getFeed); + ((App*)be_app)->MessageReceived(&getFeed); } break; } @@ -83,10 +83,10 @@ FeedController::MessageReceived(BMessage* msg) if (((Feed*)data)->IsUpdated() == true) send_data(fParseThread, msg->what, data, size); else { - BMessage* complete = new BMessage(kParseComplete); - complete->AddString("feed_name", ((Feed*)data)->GetTitle()); - complete->AddInt32("entry_count", 0); - ((App*)be_app)->MessageReceived(complete); + BMessage complete(kParseComplete); + complete.AddString("feed_name", ((Feed*)data)->GetTitle()); + complete.AddInt32("entry_count", 0); + ((App*)be_app)->MessageReceived(&complete); } i++; } @@ -118,25 +118,25 @@ int32 FeedController::_DownloadLoop(void* ignored) { thread_id sender; - Feed* feedBuffer = new Feed(); + Feed* feedBuffer = (Feed*)malloc(sizeof(Feed)); while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) { std::cout << "Downloading feed from " << feedBuffer->GetXmlUrl().UrlString() << "…\n"; - BMessage* downloadInit = new BMessage(kDownloadStart); - downloadInit->AddString("feed", feedBuffer->GetTitle()); - ((App*)be_app)->MessageReceived(downloadInit); + BMessage downloadInit = BMessage(kDownloadStart); + downloadInit.AddString("feed", feedBuffer->GetTitle()); + ((App*)be_app)->MessageReceived(&downloadInit); if (feedBuffer->Fetch()) { - BMessage* downloaded = new BMessage(kDownloadComplete); - downloaded->AddData("feeds", B_RAW_TYPE, feedBuffer, sizeof(Feed)); - ((App*)be_app)->MessageReceived(downloaded); + BMessage downloaded = BMessage(kDownloadComplete); + downloaded.AddData("feeds", B_RAW_TYPE, feedBuffer, sizeof(Feed)); + ((App*)be_app)->MessageReceived(&downloaded); } else { - BMessage* failure = new BMessage(kDownloadFail); - failure->AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); - ((App*)be_app)->MessageReceived(failure); + BMessage failure = BMessage(kDownloadFail); + failure.AddString("feed_url", feedBuffer->GetXmlUrl().UrlString()); + ((App*)be_app)->MessageReceived(&failure); } } delete(feedBuffer); @@ -148,7 +148,7 @@ int32 FeedController::_ParseLoop(void* ignored) { thread_id sender; - Feed* feedBuffer = new Feed(); + Feed* feedBuffer = (Feed*)malloc(sizeof(Feed)); while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) { BList entries; @@ -162,7 +162,10 @@ FeedController::_ParseLoop(void* ignored) feed->Parse(); entries = feed->GetNewEntries(); feedTitle = feed->GetTitle(); - delete(feed); + + for (int i = 0; i < entries.CountItems(); i++) + ((Entry*)entries.ItemAt(i))->Filetize(outDir); + delete feed; } else if (feedBuffer->IsRss()) { RssFeed* feed = (RssFeed*)malloc(sizeof(RssFeed)); @@ -170,26 +173,26 @@ FeedController::_ParseLoop(void* ignored) feed->Parse(); entries = feed->GetNewEntries(); feedTitle = feed->GetTitle(); - delete(feed); + + for (int i = 0; i < entries.CountItems(); i++) + ((Entry*)entries.ItemAt(i))->Filetize(outDir); + delete feed; } if (feedBuffer->IsAtom() || feedBuffer->IsRss()) { - for (int i = 0; i < entries.CountItems(); i++) - ((Entry*)entries.ItemAt(i))->Filetize(outDir); - - BMessage* complete = new BMessage(kParseComplete); - complete->AddString("feed_name", feedTitle); - complete->AddInt32("entry_count", entries.CountItems()); - ((App*)be_app)->MessageReceived(complete); + BMessage complete = BMessage(kParseComplete); + complete.AddString("feed_name", feedTitle); + complete.AddInt32("entry_count", entries.CountItems()); + ((App*)be_app)->MessageReceived(&complete); } else { - BMessage* failure = new BMessage(kParseFail); - failure->AddString("feed_url", feedUrl.UrlString()); - ((App*)be_app)->MessageReceived(failure); + BMessage failure = BMessage(kParseFail); + failure.AddString("feed_url", feedUrl.UrlString()); + ((App*)be_app)->MessageReceived(&failure); } } - + delete (feedBuffer); return 0; } diff --git a/src/FeedController.h b/src/FeedController.h index ed7f694..233063f 100644 --- a/src/FeedController.h +++ b/src/FeedController.h @@ -29,6 +29,7 @@ class FeedController{ public: FeedController(); ~FeedController(); + void MessageReceived(BMessage* msg); static BList SubscribedFeeds(); diff --git a/src/FeedEditWindow.cpp b/src/FeedEditWindow.cpp index d2935b3..465272b 100644 --- a/src/FeedEditWindow.cpp +++ b/src/FeedEditWindow.cpp @@ -137,11 +137,12 @@ FeedEditWindow::_SaveFeed() fFeed->SetXmlUrl(BUrl(urlString)); fFeed->Filetize(); - BMessage* enqueueUpdated = new BMessage(kEnqueueFeed); - enqueueUpdated->AddData("feeds", B_RAW_TYPE, (void*)fFeed, sizeof(Feed)); + BMessage edited(kFeedsEdited); + BMessage enqueueUpdated(kEnqueueFeed); + enqueueUpdated.AddData("feeds", B_RAW_TYPE, (void*)fFeed, sizeof(Feed)); - ((App*)be_app)->MessageReceived(enqueueUpdated); - ((App*)be_app)->PostMessage(new BMessage(kFeedsEdited)); + ((App*)be_app)->MessageReceived(&enqueueUpdated); + ((App*)be_app)->PostMessage(&edited); Quit(); } @@ -150,7 +151,8 @@ void FeedEditWindow::_DeleteFeed() { fFeed->Unfiletize(); - ((App*)be_app)->PostMessage(new BMessage(kFeedsEdited)); + BMessage edited(kFeedsEdited); + ((App*)be_app)->PostMessage(&edited); Quit(); } diff --git a/src/FeedsView.cpp b/src/FeedsView.cpp index ab532ff..0d72c15 100644 --- a/src/FeedsView.cpp +++ b/src/FeedsView.cpp @@ -13,8 +13,6 @@ #include #include -#include - #include "App.h" #include "Feed.h" #include "FeedController.h" @@ -52,7 +50,6 @@ FeedsView::MessageReceived(BMessage* msg) case kFeedsEditButton: { _EditSelectedFeed(); - _PopulateFeedList(); break; } case kFeedsSelected: @@ -180,12 +177,17 @@ FeedsView::_PopulateFeedList() BList feeds = FeedController::SubscribedFeeds(); int32 selected = fFeedsListView->CurrentSelection(); - fFeedsListView->MakeEmpty(); + for (int i = fFeedsListView->CountItems(); i >= 0; i--) + delete ((FeedListItem*)fFeedsListView->RemoveItem(i)); + for (int i = 0; i < feeds.CountItems(); i++) { FeedListItem* item = new FeedListItem((Feed*)feeds.ItemAt(i)); fFeedsListView->AddItem(item); } + for (int i = feeds.CountItems(); i >= 0; i--) + delete ((Feed*)feeds.RemoveItem(i)); + if (fFeedsListView->CountItems() < selected) selected = fFeedsListView->CountItems(); fFeedsListView->Select(selected); diff --git a/src/Notifier.cpp b/src/Notifier.cpp index b4f1070..4a28de9 100644 --- a/src/Notifier.cpp +++ b/src/Notifier.cpp @@ -134,11 +134,11 @@ Notifier::_DownloadFailNotification(BString feedUrl) void Notifier::_UpdateProgress() { - BMessage* progress = new BMessage(kProgress); - progress->AddInt32("max", fEnqueuedFeeds); - progress->AddInt32("current", fFeedsInProgress); + BMessage progress = BMessage(kProgress); + progress.AddInt32("max", fEnqueuedFeeds); + progress.AddInt32("current", fFeedsInProgress); - ((App*)be_app)->MessageReceived(progress); + ((App*)be_app)->MessageReceived(&progress); if (fFeedsInProgress == 0) fEnqueuedFeeds = 0; diff --git a/src/RssFeed.cpp b/src/RssFeed.cpp index 80c7e24..250694d 100644 --- a/src/RssFeed.cpp +++ b/src/RssFeed.cpp @@ -59,8 +59,7 @@ RssFeed::RootParse(tinyxml2::XMLElement* xchan) void RssFeed::EntryParse(tinyxml2::XMLElement* xitem) { - Entry* newEntry = (Entry*)malloc(sizeof(Entry)); - newEntry = new Entry(); + Entry* newEntry = new Entry(); newEntry->SetTitle(xitem->FirstChildElement("title")); newEntry->SetDesc(xitem->FirstChildElement("description")); diff --git a/src/UpdatesView.cpp b/src/UpdatesView.cpp index a98d662..4ea75fe 100644 --- a/src/UpdatesView.cpp +++ b/src/UpdatesView.cpp @@ -93,7 +93,7 @@ UpdatesView::_InitInterface() fIntervalSlider->SetHashMarkCount(26); fIntervalSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); fIntervalSlider->SetLimitLabels("Never", "24 hours"); - fIntervalSlider->SetModificationMessage(new BMessage('iiii')); + fIntervalSlider->SetModificationMessage(new BMessage(kIntervalChanged)); // Display current settings