void do_work(const Iter first, const Iter last, size_t thread_index) { using namespace std; auto mean = calc_mean(first, last); local_results[thread_index] = mean; b.wait(); if (thread_index == num_threads - 1) { cout << "local means: "; print_all(local_results.begin(), local_results.end()); global_mean = std::accumulate(local_results.begin(), local_results.end(), 0) / num_threads; cout << "global mean: " << global_mean << endl; // TODO: local mean of this (master) thread } b.wait(); const auto variance = calc_variance(first, last, global_mean); local_results[thread_index] = variance; b.wait(); if(thread_index == num_threads - 1) { cout << "local variance: "; print_all(local_results.begin(), local_results.end()); cout << endl; global_deviation = sqrt(std::accumulate(local_results.begin(), local_results.end(), 0)/num_threads); } }
void Role::onCollisionEnter(GameObject* collision){ //CCLOG("++===============Collision Enter======================++"); //如果撞到障碍物 就把Fever状态设计成enable if (collision->getObjType() == Object_Block && _rState != Role_Bruise) {//障碍物 Barrier* barrier = dynamic_cast<Barrier*>(collision); switch (barrier->getBarrierType()) { case Barrier_Gear: case Barrier_Stab: case Barrier_Stone: case Barrier_Rocket:{ if (_skState == Skill_Sprint) { this->removeObject(collision); break; } _rState = Role_Bruise; if (GameLogic::Singleton()->getFeverState() == Fever_doing) { GameLogic::Singleton()->setMultiple(30); GameLogic::Singleton()->setFeverState(Fever_unable); GameLogic::Singleton()->getPView()->getProgress()->setPercentage(0); } float bloodValue = GameLogic::Singleton()->getBlood(); GameLogic::Singleton()->setBlood(bloodValue -= bloodValue * 0.3);//30% CCCallFunc* callFunc = CCCallFuncND::create(this,callfuncND_selector(Role::bruiseFunc),this); this->runAction(CCSequence::create(CCBlink::create(2.0f,8),callFunc,NULL)); } break; case Barrier_Step: break; default: CCLOG("+==============fail to get Barrier Type=================+"); exit(EXIT_FAILURE); break; } }else if(collision->getObjType() == Object_Prop){//道具,添加到道具栏中 SimpleAudioEngine::sharedEngine()->playEffect(S_GAIN); Props* prop = dynamic_cast<Props*>(collision); switch (prop->getPropType()) { case Prop_Sprint: case Prop_Blood: case Prop_Wave:{ //先在工具栏设置类型 GameLogic::Singleton()->getPView()->drawPropToBox(prop->getPropType()); //删除该道具并且放入到工具栏中 GameLogic::Singleton()->getPView()->removeChild(prop); GameLogic::Singleton()->getPView()->destroyBody(prop); GameLogic::Singleton()->deleteObject(prop); } break; default: CCLOG("+==============fail to get Prop Type=================+"); exit(EXIT_FAILURE); break; } } }
Task* getNextTask() { std::unique_lock<std::mutex> counterLock(m_threadCounterMutex); m_threadsDoneCount++; if (m_threadsDoneCount >= m_totalThreads) { while (!m_queueSemaphore.wait_for(std::chrono::milliseconds(100))) { if (m_closeRequested) { m_closing = true; m_barrier.notify_all(); return nullptr; } } m_threadsDoneCount = 0; m_currentProblem = m_tasks.front().problemSpace().begin(); } counterLock.unlock(); m_barrier.wait_until_condition([this]() { return m_closing.load(); }); if (m_closing) { return nullptr; } return &m_tasks.front(); }
void GameplayScene::loadMapFromFile(std::string filePath) { std::string type; int pos_x,pos_y; std::ifstream file; file.open(filePath.c_str()); if( !file.good() ) return; while(1){ file>>type; file>>pos_x; file>>pos_y; if (file.eof()) break; if(type=="Brick"){ Brick *brick = new Brick(this,resourceManager.getTextureFromMap("Brick")); brick->setPosition(pos_x,pos_y); addEntity(brick); ball->addCollisionMaker(brick); this->entitiesLeft++; } if(type=="SolidBrick"){ SolidBrick *solidBrick = new SolidBrick(this,resourceManager.getTextureFromMap("SolidBrick")); solidBrick->setPosition(pos_x,pos_y); addEntity(solidBrick); ball->addCollisionMaker(solidBrick); this->entitiesLeft++; } if(type=="Barrier"){ Barrier *barrier = new Barrier(this,resourceManager.getTextureFromMap("Barrier")); barrier->setPosition(pos_x,pos_y); addEntity(barrier); ball->addCollisionMaker(barrier); } } file.close(); }
/** Update the enabled state of all the widgets. */ void BarrierEditor::updateEnabled() { bool canEdit = false; if(_ui->barrierTable->selectionModel()) { canEdit = _ui->barrierTable->selectionModel()->hasSelection(); } _ui->removeBarrier->setEnabled(canEdit); // Tweak canEdit determination with enabled state. */ if (canEdit) { Barrier* b = selectedBarrier(); canEdit = b != NULL && b->isEnabled(); } bool canAdd = _dataModel != NULL && !_dataModel->isFull(); _ui->addBarrier->setEnabled(canAdd); _ui->slitNumSelect->setEnabled(canEdit); Barrier::NumSlits num = numSlitsSelected(); const bool canEditSlit = canEdit && num != Barrier::ZERO_SLITS; _ui->slitWidth->setEnabled(canEditSlit); const bool canEditSlitSep = canEdit && num == Barrier::TWO_SLITS; _ui->slitSeparation->setEnabled(canEditSlitSep); }
/** Code to execute in the thread. * Executes loop() in each cycle. This is the default implementation and if * you need a more specific behaviour you can override this run() method and * ignore loop(). * Although this method is declared virtual, it should not be overridden, other * than with the following trivial snippet: * @code * protected: virtual void run() { Thread::run(); } * @endcode * The reason not to do other changes is that it contains complex house keeping * code that the system relies on. The reason for still allowing the override is * solely to make reading back traces in your debugger easier. Because now there * the class name of the thread sub-class will appear in the back trace, while * it would not otherwise. */ void Thread::run() { if ( __op_mode == OPMODE_WAITFORWAKEUP ) { // Wait for initial wakeup // __sleep_mutex has been locked in entry() already! while (__pending_wakeups == 0) { __waiting_for_wakeup = true; __sleep_condition->wait(); } __pending_wakeups -= 1; __sleep_mutex->unlock(); } forever { loopinterrupt_antistarve_mutex->stopby(); loop_mutex->lock(); if ( ! finalize_prepared ) { __loop_done = false; loop(); } loop_mutex->unlock(); __loop_done_mutex->lock(); __loop_done = true; __loop_done_mutex->unlock(); __loop_done_waitcond->wake_all(); test_cancel(); if ( __op_mode == OPMODE_WAITFORWAKEUP ) { if ( __barrier ) { __sleep_mutex->lock(); Barrier *b = __barrier; __barrier = NULL; __sleep_mutex->unlock(); b->wait(); __sleep_mutex->lock(); } else { __sleep_mutex->lock(); } while (__pending_wakeups == 0) { __waiting_for_wakeup = true; __sleep_condition->wait(); } __pending_wakeups -= 1; __sleep_mutex->unlock(); } yield(); } }
void GameScene::addTower(Vec2 pos) { Barrier* barrier = Barrier::create("tower.png", 5, 2); barrier->setPosition(pos.x,pos.y+60); float time = (pos.y+60)/winsize.height*20; auto moveAct = MoveTo::create(time, Vec2(pos.x,ENEMY_MIN_POS)); auto funcAct = CallFuncN::create(CC_CALLBACK_1(GameScene::removeBarrier, this)); barrier->runAction(Sequence::create(moveAct,funcAct, NULL)); barrierVec.push_back(barrier); addChild(barrier,Game_Layer_Tank); }
Barrier* Barrier::create(const char *pic, int index, int blood) { Barrier* barrier = new Barrier(); if (!barrier->initWithFile(pic)) { CC_SAFE_DELETE(barrier); return NULL; } barrier->index = index; barrier->blood = blood; return barrier; }
Barrier* Barrier::create(int type) { Barrier *pRet = new(std::nothrow) Barrier(); if (pRet && pRet->init(type)) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = nullptr; return nullptr; } }
Error operator()(AsyncLoaderTaskContext& ctx) { if(m_count) { auto x = m_count->fetchAdd(1); if(m_id >= 0) { if(m_id != static_cast<I32>(x)) { ANKI_LOGE("Wrong excecution order"); return ErrorCode::FUNCTION_FAILED; } } } if(m_sleepTime != 0.0) { HighRezTimer::sleep(m_sleepTime); } if(m_barrier) { m_barrier->wait(); } ctx.m_pause = m_pause; ctx.m_resubmitTask = m_resubmit; m_resubmit = false; return ErrorCode::NONE; }
// Event - Barrier_Build void GameUI::BarrierNumberSub(EventCustom *event) { Barrier *barrier = (Barrier*)event->getUserData(); int barrierType = barrier->GetBarrierType(); for (int i = 0; i < 4; i++) { BarrierUI *barrierUI = (BarrierUI*)getChildByTag(i); if (barrierUI->GetBarrierType() == barrierType) { barrierUI->Sub(); break; } } }
/* * this is called by our "fake" BpGraphicBufferProducer. We package the * data and reply Parcel and forward them to the calling thread. */ virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { this->code = code; this->data = &data; this->reply = reply; android_atomic_acquire_store(0, &memoryBarrier); if (exitPending) { // if we've exited, we run the message synchronously right here handleMessage(Message(MSG_API_CALL)); } else { barrier.close(); looper->sendMessage(this, Message(MSG_API_CALL)); barrier.wait(); } return NO_ERROR; }
std::vector<std::future<size_t>> unnamed(const size_t max, const size_t threads, MpScFifo<size_t> &list, Barrier &barrier) { std::atomic_thread_fence(std::memory_order::memory_order_release); std::vector<std::future<size_t>> v; for (size_t i = 0; i < threads; ++i) { /** * setup threads */ std::packaged_task<size_t()> task([max, i, &barrier, &list]() { std::atomic_thread_fence(std::memory_order::memory_order_acquire); barrier.await(); std::cout << "start\n"; std::flush(std::cout); size_t cnt = i * max; const size_t maxs = max + cnt; while (cnt < maxs) { list.push_back(cnt++); } std::cout << "start-done\n"; std::flush(std::cout); return size_t(0); }); v.push_back(task.get_future()); std::thread t(std::move(task)); t.detach(); } return v; }
int main(int argc, char **argv) { QApplication app(argc, argv); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); // qsrand(1); srand(time(0)); // srand(1); int screenWidth = 600; int screenHeight = 300; CopsScene scene; scene.setBackgroundBrush(Qt::black); scene.setSceneRect(0, 0, screenWidth, screenHeight); scene.setItemIndexMethod(QGraphicsScene::NoIndex); Cops *helicops = new Cops(); helicops->setPos(50, 50); scene.addItem(helicops); QGraphicsRectItem *downRect = new QGraphicsRectItem(0, 0, screenWidth, 10); downRect->setBrush(Qt::green); downRect->setPos(0,screenHeight - 10); scene.addItem(downRect); QGraphicsRectItem *upRect = new QGraphicsRectItem(0, 0, screenWidth, 10); upRect->setBrush(Qt::green); upRect->setPos(0,0); scene.addItem(upRect); Barrier *barrier = new Barrier(0, 0, 20, 70); barrier->setBrush(Qt::green); barrier->setPos(400, 100); scene.addItem(barrier); QGraphicsView view(&scene); view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view.setRenderHint(QPainter::Antialiasing); view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setDragMode(QGraphicsView::ScrollHandDrag); view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Helicops!")); view.resize(screenWidth + 20, screenHeight + 20); view.show(); return app.exec(); }
Barrier * Barrier::creates( std::string pname,int barrierIndex,int barrierBlood){//敌机类 //创建敌方坦克 Barrier *barrier = new Barrier(); if (barrier->initWithFile(pname.c_str())){ //初始障碍物的类型信息 barrier->barrierIndex = barrierIndex; //障碍物的血量 barrier->barrierBlood = barrierBlood; //设置为系统自动管理 barrier->autorelease(); //获取图片大小 barrier->barrierSize = barrier->getContentSize(); return barrier; } CC_SAFE_DELETE(barrier);//清除资源 return NULL; }
/* * here we run on the binder calling thread. All we've got to do is * call the real BpGraphicBufferProducer. */ virtual void handleMessage(const Message& message) { android_atomic_release_load(&memoryBarrier); if (message.what == MSG_API_CALL) { impl->asBinder()->transact(code, data[0], reply); barrier.open(); } else if (message.what == MSG_EXIT) { exitRequested = true; } }
void GameScene::enemyTankShoot(float dt) { for (auto it=enemyTankVec.begin(); it!=enemyTankVec.end(); ++it) { EnemyTank* enemyTank = (EnemyTank*)(*it); int index = rand()%3; auto waitAct = DelayTime::create(index*0.005); Animate* aniAct = Animate::create(tankGunAnimation[enemyTank->getEnemyTankIndex()]); auto shootAct = CallFuncN::create(CC_CALLBACK_1(GameScene::addEnemyTankBullet, this)); enemyTank->enemyTankGun->runAction(Sequence::create(waitAct,aniAct,shootAct, NULL)); } for (auto it=barrierVec.begin(); it!=barrierVec.end(); ++it) { Barrier* barrier = (Barrier*)(*it); if (barrier->getBarrierIndex() == 5) { addBarrierBullet(barrier); } } }
void BarrierEditor::updateNumSlits() { Barrier* b = selectedBarrier(); if(b) { QObject* sender = QObject::sender(); if(sender) { if(sender == _ui->zeroSlits) { b->setNumSlits(Barrier::ZERO_SLITS); } else if(sender == _ui->oneSlit) { b->setNumSlits(Barrier::ONE_SLIT); } else if(sender == _ui->twoSlits) { b->setNumSlits(Barrier::TWO_SLITS); } } updateEnabled(); } }
void constructBarriers(Game *theGame, const Vector<F32> &barrier, F32 width) { Vector<Point> vec; for(S32 i = 1; i < barrier.size(); i += 2) { float x = barrier[i-1]; float y = barrier[i]; vec.push_back(Point(x,y)); } if(vec.size() <= 1) return; Vector<Point> barrierEnds; constructBarrierPoints(vec, width, barrierEnds); for(S32 i = 0; i < barrierEnds.size(); i += 2) { Barrier *b = new Barrier(barrierEnds[i], barrierEnds[i+1], width); b->addToGame(theGame); } }
/* As usual, our open() will create one or more threads where we'll do the interesting work. */ int Test::open(void * _unused) { ACE_UNUSED_ARG(_unused); // One thing about the barrier: You have to tell it how many // threads it will be synching. The threads() mutator on my // Barrier class lets you do that and hides the implementation // details at the same time. barrier_.threads(threads_); // Activate the tasks as usual... return this->activate(THR_NEW_LWP, threads_, 1); }
Error operator()(AsyncLoaderTaskContext& ctx) { void* mem = m_alloc.allocate(10); if(!mem) return ErrorCode::FUNCTION_FAILED; HighRezTimer::sleep(0.1); m_alloc.deallocate(mem, 10); if(m_barrier) { m_barrier->wait(); } return ErrorCode::NONE; }
// this method will be executed on up to 8 threads, depending on the // second parameter to pool.run(). In the case of 8 threads, each of // them will be invoked with a different threadIdx (ranging 0..7), while // numWorkerThreads will be 8. void entry(int threadIdx, int numWorkerThreads) { double partialSum = 0; printf("DoWork::entry(%d, %d)\n", threadIdx, numWorkerThreads); fflush(stdout); int i; for (i = threadIdx; i < 500000000; i += numWorkerThreads) { if (!i) continue; double d = i; partialSum += 1.0 / (d * d); } printf("Thread %d: waiting for others...\n", threadIdx); fflush(stdout); barrier.checkout(); printf("Thread %d: continuing\n", threadIdx); fflush(stdout); for (; i < 1000000000; i += numWorkerThreads) { double d = i; partialSum += 1.0 / (d*d); } data[threadIdx] = partialSum; }
void retireTask(Task* task) { std::unique_lock<std::mutex> counterLock(m_threadCounterMutex); m_threadsDoneCount++; if (m_threadsDoneCount >= m_totalThreads) { task->notifyComplete(); m_threadsDoneCount = 0; std::unique_lock<std::mutex> queueLock(m_queueMutex); m_tasks.pop(); if (m_tasks.empty()) { m_tasksComplete.notify_all(); } } counterLock.unlock(); m_barrier.wait(); }
void GameScene::addBarrierBullet(Node* node) { Barrier* barrier = (Barrier*)node; auto barrierBullet = Sprite::create(enemyName[barrier->getBarrierIndex()-1].c_str()); enemyBazooka->addChild(barrierBullet); barrierBullet->setPosition(barrier->getPosition()); float angle = 0.0; auto posDiff = Vec2(hero->tankBody->getPosition().x-barrier->getPosition().x,hero->tankBody->getPosition().y-barrier->getPosition().y); if (posDiff.x > 0) { angle = 90-atan(posDiff.y/posDiff.x)*180/pi; } else { angle = -atan(posDiff.y/posDiff.x)*180/pi-90; } auto moveAct = MoveTo::create(5, Vec2(barrier->getPosition().x+1024*posDiff.x,barrier->getPosition().y+800*posDiff.y)); barrierBullet->setRotation(angle); auto funcAct = CallFuncN::create(CC_CALLBACK_1(GameScene::removeEnemyTankBazooka, this)); barrierBullet->runAction(Sequence::create(moveAct,funcAct, NULL)); }
/** * Tests the situation in which the alt disable sequence is running, and has reached guard B, * where some guard C (B < C) had fired after all guards had been enabled. Guard A (A < B < C) is then fired. */ static TestResult test4() { BEGIN_TEST() SetUp setup; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); WaitingGuard* guard1; Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); talt->guards[0] = new TestGuard(&result); talt->guards[1] = guard1 = new WaitingGuard(&result,false); talt->guards[2] = new TestGuard(&result); talt->guards[3] = new TestGuard(&result); EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); CPPCSP_Yield(); { ScopedForking forking; set<EventList> expA_0,expA_1; expA_0 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; expA_0 += tuple_list_of (us,alter,alter) //We free them ; //In 0, they don't block on the barrier expA_1 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the alt (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; expA_1 += tuple_list_of (us,alter,alter) //We free them ; set<EventList> actA; { RecordEvents _(&actA); //Guard is already fired: forking.fork(_alter); while (AtomicGet(&(alter->alting)) != ___ALTING_WAITING) { Thread_Yield(); } talt->guards[2]->fire(); guard1->waitForWait(); talt->guards[0]->fire(); guard1->free(); } barrierEnd.sync(); ASSERTEQ1OF2(expA_0,expA_1,actA,"Events not as expected in part A",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(0,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[0],result,"Alternative did not activate the correct guard",__LINE__); } END_TEST("Alt test 4"); }
/** * Tests the situation in an enabling sequence where the alt enables guard A, * then while it is enabling guard B (A < B), guard A fires. Even though the guard * has already been dealt, the alt should notice, and not block at the end of its enable */ static TestResult test2() { BEGIN_TEST() SetUp setup; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); WaitingGuard* guard1; WaitingGuard* guard2; Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); talt->guards[0] = new TestGuard(&result); talt->guards[1] = guard1 = new WaitingGuard(&result,true); talt->guards[2] = guard2 = new WaitingGuard(&result,true); talt->guards[3] = new TestGuard(&result); EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); ScopedForking forking; set<EventList> expA_0,expA_1; //expA_0 is blank (the version where they don't block on the barrier) expA_1 += tuple_list_of (alter,NullProcessPtr,NullProcessPtr) //They block on the barrier ; set<EventList> actA; { RecordEvents _(&actA); forking.fork(_alter); guard1->waitForWait(); talt->guards[0]->fire(); guard1->free(); guard2->waitForWait(); guard2->free(); } barrierEnd.sync(); ASSERTEQ1OF2(expA_0,expA_1,actA,"Events not as expected in part A",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(0,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[0],result,"Alternative did not activate the correct guard",__LINE__); END_TEST("Alt test 2"); }
/** * Tests alts blocking when no guards are ready, and then awaking *once* when multiple guards fire */ static TestResult test1() { BEGIN_TEST() SetUp setup; ScopedForking forking; BufferedOne2OneChannel<unsigned> c(FIFOBuffer<unsigned>::Factory(1)); Barrier barrier; ScopedBarrierEnd barrierEnd(barrier.enrolledEnd()); TestAlt* talt = new TestAlt(barrier.enrolledEnd()); Guard* result = NULL; talt->guards.resize(4); for (unsigned i = 0;i < 4;i++) { talt->guards[i] = new TestGuard(&result); } EvaluateFunction< unsigned, TestAlt >* _alter = new EvaluateFunction< unsigned, TestAlt >(*talt,c.writer()); ProcessPtr alter(getProcessPtr(_alter)); EventList expA = tuple_list_of (us,alter,alter) //We start them up (us,us,us) (us,NullProcessPtr,NullProcessPtr) //we yield (alter,NullProcessPtr,NullProcessPtr) //they must block, waiting for the guards ; EventList actA; { RecordEvents _(&actA); forking.forkInThisThread(_alter); CPPCSP_Yield(); } ASSERTEQ(expA,actA,"Events not as expected in part A",__LINE__); ASSERTEQ(alter,talt->guards[0]->process,"Data (0.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[1]->process,"Data (1.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[2]->process,"Data (2.process) not as expected",__LINE__); ASSERTEQ(alter,talt->guards[3]->process,"Data (3.process) not as expected",__LINE__); ASSERTEQ(false,talt->guards[0]->fired,"Data (0.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[1]->fired,"Data (1.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[2]->fired,"Data (2.fired) not as expected",__LINE__); ASSERTEQ(false,talt->guards[3]->fired,"Data (3.fired) not as expected",__LINE__); EventList expB = tuple_list_of (us,alter,alter) //We fire guard[3]. //Firing guards[2] and guards[1] have no effect on the run-queue (us,us,us) (us,NullProcessPtr,NullProcessPtr) //we yield (alter,NullProcessPtr,NullProcessPtr) //they block on the barrier ; EventList actB; { RecordEvents _(&actB); talt->guards[3]->fire(); talt->guards[2]->fire(); talt->guards[1]->fire(); CPPCSP_Yield(); } ASSERTEQ(expB,actB,"Events not as expected in part B",__LINE__); assertAllGuardsEmpty(talt); barrierEnd.sync(); barrierEnd.sync(); unsigned sel; c.reader() >> sel; ASSERTEQ(1,sel,"Alternative did not select the correct guard",__LINE__); ASSERTEQ(talt->guards[1],result,"Alternative did not activate the correct guard",__LINE__); delete talt; END_TEST("Alt Test 1"); }
// // All hardware threads start execution here // int main() { Fiber::initSelf(); #if 0 Core::current()->addFiber(new TestFiber('0' + Core::currentStrandId())); while (true) Core::reschedule(); #endif render::Rasterizer rasterizer(kFbWidth, kFbHeight); render::RenderTarget renderTarget; renderTarget.setColorBuffer(&gColorBuffer); renderTarget.setZBuffer(&gZBuffer); #if DRAW_TORUS #if GOURAND_SHADER GourandVertexShader vertexShader; GourandPixelShader pixelShader(&renderTarget); #else PhongVertexShader vertexShader; PhongPixelShader pixelShader(&renderTarget); #endif const float *vertices = kTorusVertices; int numVertices = kNumTorusVertices; const int *indices = kTorusIndices; int numIndices = kNumTorusIndices; #elif DRAW_CUBE TextureVertexShader vertexShader; TexturePixelShader pixelShader(&renderTarget); pixelShader.bindTexture(&texture); const float *vertices = kCubeVertices; int numVertices = kNumCubeVertices; const int *indices = kCubeIndices; int numIndices = kNumCubeIndices; #elif DRAW_TEAPOT #if GOURAND_SHADER GourandVertexShader vertexShader; GourandPixelShader pixelShader(&renderTarget); #else PhongVertexShader vertexShader; PhongPixelShader pixelShader(&renderTarget); #endif const float *vertices = kTeapotVertices; int numVertices = kNumTeapotVertices; const int *indices = kTeapotIndices; int numIndices = kNumTeapotIndices; #endif const float kAspectRatio = float(kFbWidth) / float(kFbHeight); const float kProjCoeff[4][4] = { { 1.0f / kAspectRatio, 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0, 0.0 }, }; vertexShader.setProjectionMatrix(Matrix(kProjCoeff)); #if DRAW_TORUS vertexShader.applyTransform(translate(0.0f, 0.0f, 1.5f)); vertexShader.applyTransform(rotateAboutAxis(M_PI / 3.5, 0.707f, 0.707f, 0.0f)); #elif DRAW_CUBE vertexShader.applyTransform(translate(0.0f, 0.0f, 2.0f)); vertexShader.applyTransform(rotateAboutAxis(M_PI / 3.5, 0.707f, 0.707f, 0.0f)); #elif DRAW_TEAPOT vertexShader.applyTransform(translate(0.0f, 0.1f, 0.25f)); vertexShader.applyTransform(rotateAboutAxis(M_PI, -1.0f, 0.0f, 0.0f)); #endif Matrix rotateStepMatrix(rotateAboutAxis(M_PI / 8, 0.707f, 0.707f, 0.0f)); pixelShader.enableZBuffer(true); // pixelShader.enableBlend(true); if (Core::currentStrandId() == 0) gVertexParams = (float*) allocMem(16384 * sizeof(float)); gInitBarrier.wait(); int numVertexParams = vertexShader.getNumParams(); for (int frame = 0; frame < 1; frame++) { // // Geometry phase. Statically assign groups of 16 vertices to threads. Although these may be // handled in arbitrary order, they are put into gVertexParams in proper order (this is a sort // middle architecture, and gVertexParams is in the middle). // int vertexIndex = Core::currentStrandId() * 16; while (vertexIndex < numVertices) { vertexShader.processVertices(gVertexParams + vertexShader.getNumParams() * vertexIndex, vertices + vertexShader.getNumAttribs() * vertexIndex, numVertices - vertexIndex); vertexIndex += 16 * kNumCores * kHardwareThreadsPerCore; } if (Core::currentStrandId() == 0) gNextTileIndex = 0; vertexShader.applyTransform(rotateStepMatrix); gGeometryBarrier.wait(); // // Pixel phase // #if WIREFRAME if (Core::currentStrandId() == 0) { // Only thread 0 does wireframes for (int tileY = 0; tileY < kFbHeight; tileY += kTileSize) { for (int tileX = 0; tileX < kFbWidth; tileX += kTileSize) renderTarget.getColorBuffer()->clearTile(tileX, tileY, 0); } for (int vidx = 0; vidx < numIndices; vidx += 3) { int offset0 = indices[vidx] * numVertexParams; int offset1 = indices[vidx + 1] * numVertexParams; int offset2 = indices[vidx + 2] * numVertexParams; float x0 = gVertexParams[offset0 + kParamX]; float y0 = gVertexParams[offset0 + kParamY]; float x1 = gVertexParams[offset1 + kParamX]; float y1 = gVertexParams[offset1 + kParamY]; float x2 = gVertexParams[offset2 + kParamX]; float y2 = gVertexParams[offset2 + kParamY]; // Convert screen space coordinates to raster coordinates int x0Rast = x0 * kFbWidth / 2 + kFbWidth / 2; int y0Rast = y0 * kFbHeight / 2 + kFbHeight / 2; int x1Rast = x1 * kFbWidth / 2 + kFbWidth / 2; int y1Rast = y1 * kFbHeight / 2 + kFbHeight / 2; int x2Rast = x2 * kFbWidth / 2 + kFbWidth / 2; int y2Rast = y2 * kFbHeight / 2 + kFbHeight / 2; drawLine(&gColorBuffer, x0Rast, y0Rast, x1Rast, y1Rast, 0xffffffff); drawLine(&gColorBuffer, x1Rast, y1Rast, x2Rast, y2Rast, 0xffffffff); drawLine(&gColorBuffer, x2Rast, y2Rast, x0Rast, y0Rast, 0xffffffff); } for (int tileY = 0; tileY < kFbHeight; tileY += kTileSize) { for (int tileX = 0; tileX < kFbWidth; tileX += kTileSize) renderTarget.getColorBuffer()->flushTile(tileX, tileY); } } #else // #if WIREFRAME while (gNextTileIndex < kMaxTileIndex) { // Grab the next available tile to begin working on. int myTileIndex = __sync_fetch_and_add(&gNextTileIndex, 1); if (myTileIndex >= kMaxTileIndex) break; int tileX = (myTileIndex % kTilesPerRow) * kTileSize; int tileY = (myTileIndex / kTilesPerRow) * kTileSize; renderTarget.getColorBuffer()->clearTile(tileX, tileY, 0); if (pixelShader.isZBufferEnabled()) { // XXX Ideally, we'd initialize to infinity, but comparisons // with infinity are broken in hardware. For now, initialize // to a very large number renderTarget.getZBuffer()->clearTile(tileX, tileY, 0x7e000000); } // Cycle through all triangles and attempt to render into this // NxN tile. for (int vidx = 0; vidx < numIndices; vidx += 3) { int offset0 = indices[vidx] * numVertexParams; int offset1 = indices[vidx + 1] * numVertexParams; int offset2 = indices[vidx + 2] * numVertexParams; float x0 = gVertexParams[offset0 + kParamX]; float y0 = gVertexParams[offset0 + kParamY]; float z0 = gVertexParams[offset0 + kParamZ]; float x1 = gVertexParams[offset1 + kParamX]; float y1 = gVertexParams[offset1 + kParamY]; float z1 = gVertexParams[offset1 + kParamZ]; float x2 = gVertexParams[offset2 + kParamX]; float y2 = gVertexParams[offset2 + kParamY]; float z2 = gVertexParams[offset2 + kParamZ]; // Convert screen space coordinates to raster coordinates int x0Rast = x0 * kFbWidth / 2 + kFbWidth / 2; int y0Rast = y0 * kFbHeight / 2 + kFbHeight / 2; int x1Rast = x1 * kFbWidth / 2 + kFbWidth / 2; int y1Rast = y1 * kFbHeight / 2 + kFbHeight / 2; int x2Rast = x2 * kFbWidth / 2 + kFbWidth / 2; int y2Rast = y2 * kFbHeight / 2 + kFbHeight / 2; #if ENABLE_BOUNDING_BOX_CHECK // Bounding box check. If triangles are not within this tile, // skip them. int xMax = tileX + kTileSize; int yMax = tileY + kTileSize; if ((x0Rast < tileX && x1Rast < tileX && x2Rast < tileX) || (y0Rast < tileY && y1Rast < tileY && y2Rast < tileY) || (x0Rast > xMax && x1Rast > xMax && x2Rast > xMax) || (y0Rast > yMax && y1Rast > yMax && y2Rast > yMax)) continue; #endif #if ENABLE_BACKFACE_CULL // Backface cull triangles that are facing away from camera. // We also remove triangles that are edge on here, since they // won't be rasterized correctly. if ((x1Rast - x0Rast) * (y2Rast - y0Rast) - (y1Rast - y0Rast) * (x2Rast - x0Rast) <= 0) continue; #endif // Set up parameters and rasterize triangle. pixelShader.setUpTriangle(x0, y0, z0, x1, y1, z1, x2, y2, z2); for (int paramI = 0; paramI < numVertexParams; paramI++) { pixelShader.setUpParam(paramI, gVertexParams[offset0 + paramI + 4], gVertexParams[offset1 + paramI + 4], gVertexParams[offset2 + paramI + 4]); } rasterizer.fillTriangle(&pixelShader, tileX, tileY, x0Rast, y0Rast, x1Rast, y1Rast, x2Rast, y2Rast); } renderTarget.getColorBuffer()->flushTile(tileX, tileY); } #endif // #if WIREFRAME gPixelBarrier.wait(); } return 0; }
/* Callback routine for synchronization of C++11 threads. */ void cpp11thread_sync(int tid, int tsize, void *data) { Barrier *barrier = reinterpret_cast<Barrier*>(data); barrier->wait(); }
inline void doBarrier(size_t tid) { return bar.doBarrier(tid); }